The whole text of the documentation to be searched within your browser. The links jump back to the pages per chapter/example.
Welcome to Inform, a design system for interactive fiction based on natural language.
Interactive fiction is a literary form which involves programming a computer so that it presents a reader with a text which can be explored. Inform aims to make the burden of learning to program such texts as light as possible. It is a tool for writers intrigued by computing, and computer programmers intrigued by writing. Perhaps these are not so very different pursuits, in their rewards and pleasures.
Writing with Inform is one of two interlinked books included with Inform: a concise but complete guide to the system. The other book is The Inform Recipe Book, a comprehensive collection of examples, showing its practical use.
These notes are arranged so that the reader can, in principle, write whole works of fiction as early as the end of Chapter 3. Each subsequent chapter then extends the range of techniques available to make livelier and more intriguing situations.
Today's Inform language (sometimes called "Inform 7") is very different from its 20th-century predecessor, which was called Inform 6. A few advanced sections of this book show how unusual effects can be achieved by mixing low-level coding in Inform 6 notation with more usual Inform text. However, most users will never need this. For information about Inform 6, see inform-fiction.org.
This book is also a guide to the Inform language, rather than a manual on how to use its supporting tools. Those tools, when used at the command line rather than inside the Inform app, have numerous features not covered here. Manuals for them are all available online: see github.com/ganelson/inform.
Inform 7 is dedicated to Emily Short and Andrew Plotkin, whose shrewd and sceptical suggestions made a contribution which can hardly be overstated. A long email correspondence with Andrew entirely subverted my original thoughts about natural-language IF, as he convinced me that the "new model" of rule-based IF was a truer foundation; while Emily's wry, witty analysis and how-about-this? cheered me at low moments, besides providing the impetus and often the specifics for a lot of the best ideas.
From the outset, I have thought of Inform 7 as no longer being a command-line compiler, but a compiler in combination with a humanising user interface. All credit for the reference implementation under Mac OS X belongs to Andrew Hunter. How simple the metaphor of an interactive book with facing pages may seem, but the coding was an enormous challenge. In 2014 Toby Nelson, my brother, put months of time into the project by rewriting and modernising the Mac OS X application: sandboxing it for the Mac App Store, giving it a more contemporary design, and much more. He continues to maintain it today.
Though David Kinder's Windows application does indeed visually follow the OS X original, the two programs were coded independently, and the programming task taken up by David was formidable indeed. Philip Chimento's Gnome-based user interface for Linux became officially part of the project in November 2007, when the first easy-to-install packages for Ubuntu and Fedora were offered. Adam Thornton gave invaluable assistance in the closed-source age of Inform to make generic Unix binaries available, too.
While Inform is not strictly speaking a project of the Interactive Fiction Technology Foundation (IFTF), it benefits enormously from the Foundation's good work. In particular, the Narrascope conferences were invaluable in the period 2017-2022, and I thank Judith Pintar and Andrew Plotkin for arranging speaking slots at them.
Inform in its widest sense incorporates work by so many people that it's simply impossible to thank all of them, but Zed Lopez, Dannii Willis, Mark Musante, Brian Rushton, Dan Fabulich, Hugo Labrande, Erik Temple, Ron Newcomb, Eric Eve, Justin de Vesine and Juhana Leinonen all deserve special mention. Many hundreds of users have filed patient and careful bug reports, keeping us on the straight and narrow. They're contributors, too.
The original development of Inform 7 was a long haul, and I would particularly like to thank Sonja Kesserich, David Cornelson and other volunteers for their early testing of a then-fragile system. The final months before the Public Beta release of Inform 7 were made more enjoyable, as well as more productive, by fruitful discussions leading to a cross-platform standard for bibliographic data and cover art. Special mentions to L. Ross Raszewski, who wrote frighteningly efficient reference software in frighteningly little time; the librarians of the IF-Archive, Andrew Plotkin, David Kinder and Paul Mazaitis; and my fellow authors of IF design systems – Mike Roberts (of the Text Adventure Development System); Kent Tessman (of Hugo); and Campbell Wild (of ADRIFT).
At the start the only panels available are a blank space in which to write the first lines of a new interactive fiction – the Source panel – and this one, the Documentation. Clicking on the other choices will do nothing.
The exception is the Settings panel, which contains some preference settings for the individual project – not the whole application. This is always available, but it controls settings which can be left alone almost all of the time.
Clicking the Go button translates the text in the Source panel into a computer program which enacts the interactive fiction, and automatically sets it going (in the Story panel, which opens as needed).
If the Source is empty of text, Inform will be unable to create anything: it needs at least one name of a location where the drama can unfold. For reasons of tradition, such locations are normally called "rooms", though people have used them to represent anything from grassy fields to states of mind and other metaphorical places.
Clicking Go with this text in the Source panel will result in a short delay, after which the Story panel will appear, from which we can explore this newly created world: an interactive fiction called "Midsummer Day". It will not be very exciting, since Inform has only five words to go on, but we can add more detail to the source at any point and then click Go again to try out the changes. (Note that there is no need to "quit" these explorations in the Story panel. When Go is clicked, any story already in progress is discarded in favour of the new version.)
Replay works identically to Go, except that it does something further: once the story is created, it automatically plays through the same commands as were typed into the previous version. For instance: suppose we click Go to bring Midsummer Day into being, and find ourselves playing the story. We type "look" and find that there is not much to see. Going back to the source, we add
so that the source now reads
Instead of clicking Go, we click Replay, and can sit back and watch what has changed. In this example, it only saves us the trouble of typing "look", but once stories become long and elaborate, Replay is invaluable: and especially when we notice in play that something very minor is wrong – a spelling error, say – and want to fix it immediately, without fuss.
If, when Go! is clicked, the text in the Source panel is not fully understood, then Inform will generate a report of the problems it found, which will open in the "Errors" panel. (Other information is also available in "Errors", but most of it is used for debugging Inform, and can be ignored.)
On the other hand, if the text was fully understood then another new panel will become available: the "Index". This is a cross-referenced index of the source, or rather, of the interactive fiction which has been generated. The Index is only an optional convenience, but becomes more and more helpful as the fiction grows larger. Its exact format does not matter for now.
The icon
always denotes a reference to a particular line in the Source text, that is, to something written in the source: clicking it opens the Source panel and jumps to that position.
The icon
indicates that more detailed information can be read further down the text in the same panel: clicking it jumps down to this more detailed report.
Lastly, the icon
hints that there is a relevant page of this manual: clicking this opens the Documentation panel and switches to it.
The Replay button demonstrates that Inform must be quietly remembering the commands typed into the last run through the story. In fact it remembers, and automatically organises, every previous run.
Inform's approach to testing interactive fiction is to treat it as being like the analysis of other turn-based games, such as chess. It would be prohibitively difficult to work out every possible combination of moves: instead, we analyse those which go somewhere, and look for significant choices. Every Queen's Gambit begins with the same first three moves (1. d4, d5; 2. c4), but then there is a choice, as the next move decides whether we have a Queen's Gambit Accepted (dxc4) or Declined (e6). Books about chess often contain great tables of such openings, which run together for a while but eventually diverge. To learn chess, one must explore all of these variations.
Inform's Skein panel is just such a table, built automatically. If we think of the list of typed commands as a thread, then the skein is (as the name suggests) braided together from all these threads. In the display, time begins at the top, with the start knot, and the threads of different play-throughs hang downwards from it.
Double-clicking on a command translates the source afresh and replays the story from start down to that command, and then stops. We are then free to continue play by typing commands into the Story panel, of course, and these commands will automatically be recorded in the Skein as a new variation of play, diverging from the previous threads.
The user interface for the Skein looks slightly different on different versions of the Inform apps (that is, the MacOS version is not quite the same as the Windows version, and so on), so this manual is not the best place to describe it. In any case, the best way to find out about it is probably to experiment.
Designing an interactive fiction can be divided into two related activities. One is the creation of the world as it appears at the start of play: where and what everything is. The other is to specify the rules of play, which shape how the player interacts with that initially created world. A new Inform project is void and without form, so to speak, with nothing created: but it starts with hundreds of standard rules already in place.
The same division between creating things, and laying down rules, is visible in Inform source text. The creation of the world is done by making unconditional factual statements about it. For example,
Inform calls sentences like these "assertions". The verb is always written in the present tense (thus the crate "is", not "will be"). Further examples are:
The words "is", "wears" and "contains" are forms of three of the basic verbs built in to Inform. There are only a few built-in assertion verbs, of which the most important are to be, to have, to carry, to wear, to contain and to support. (As we shall see, further assertion verbs can be created if needed.)
The world described by these assertions is the starting condition of the story: what happens when play begins is another matter. If somebody picks up the crate and walks off with it, then it will no longer be in the Gazebo. Mr Jones may remove his hat.
The other kind of sentence tells Inform what should happen in certain circumstances, and reads like an instruction issued to someone:
This is a "rule", and it changes the crate's behaviour. The player who tries typing "take crate", "pick up the crate" or similar will be met only with the unhelpful reply "It's far too heavy to lift." The many different kinds of thing which the player can do are called "actions", and are always written as participles: "taking …", for instance, or "putting … on …".
Inform is built on a mass of several hundred rules, some quite complex, and it could even be said that Inform is that mass of rules. We never see the complexity behind the scenes because the whole aim is to provide a basic, penny-plain, vanilla flavoured sort of realism. It would be surprising if one could put the crate inside itself, so a rule exists to forbid this. It would be surprising if one could drop something which was already on the ground, and so on. These basic rules of realism are the ones which every new Inform project starts with.
A rule always starts with a situation which it applies to, and then follows with one or more things to do. Here's an example where the situation is "Before taking the crate" – the player is just starting to try to pick the box up – and there's a three-step process to follow, but steps 2 and 3 happen only if step 1 comes out in a particular way:
The steps to follow here are called "phrases". Inform knows about 400 built-in phrases, but most of them are needed only occasionally. These three are used over and over again:
Every one of the built-in phrases has a definition somewhere in this book. The full definition of "say" will come later, but in the simple form above it writes out the given text for the player to read. (Normally this text is simply shown on screen, not spoken aloud, unless software adapted for partially sighted people is being used.) Phrase definitions are all linked to in the Phrases page of a project's Index.
An example rule from the previous section demonstrates one of Inform's conventions about punctuation, and is worth pausing to look at again.
In English grammar, it's usual to regard a full stop as closing its sentence even when it occurs inside quotation marks, provided there is no indication to the contrary, and this is also the rule used by Inform. Thus:
is read as equivalent to
Sentence breaks like this occur only when the final character of the quoted text is a full stop, question mark or exclamation mark (or one of these three followed by a close bracket) and the next word begins, in the source code, with a capital letter. A paragraph break also divides sentences, behaving as if it were a full stop.
Material in square brackets [like so] is "comment", in computing jargon: it is considered as being an aside, a private note by the author, and not read in by Inform. This allows us to make notes to ourselves like so:
Inform is all about text, so pieces of text are often quoted in Inform source. This example is typical:
Quotations always use double-quotation marks, which aren't part of the text. So the description here is just the five letters and full stop in between the marks:
That seems straightforward, but there are three conventions to watch out for.
1. Square brackets [ and ] inside quoted text don't literally mean [ and ]. They're used to describe what Inform should say, but in a non-literal way. For example,
might produce
These are called "text substitutions". They're highly flexible, and they can take many different forms.
2. Single quotation marks at the edges of words are printed as double. So:
produces
3. Texts which end with sentence-ending punctuation – full stop, question mark, exclamation mark – are printed with a line break after them. So:
would come out quite differently – this doesn't affect the appearance of the text, but only the position where the next text will appear. Something to be careful about is that this only applies when the punctuation occurs at the end of a "say", as in these examples. (It doesn't apply when a varying textual value is printed, using some text substitution, because then the pattern of where line breaks occur would be unpredictable – sometimes the value might end in a punctuation mark, sometimes not.)
These three punctuation rules for texts feel very natural with practice, and Inform users sometimes don't realise the third rule is even there, because it just seems the right thing to happen. But occasionally the rules get in the way of what we want to do. (For instance, how do we get a literal [ or ]? What if we want a single quote mark where Inform thinks we want a double, or vice versa?) So we'll come back to these rules in more detail in the chapter on Text.
Inform also reads other punctuation marks. Colon ":" and semicolon ";" turned up in the previous section, in the writing of rules.
As these examples begin to show, Inform source imitates the conventions of printed books and newspapers whenever there is a question of how to write something not easily fitting into words. The first example of this is how Inform handles headings, but to see why these are so useful we first look at Problems.
How Inform reads quoted text for a fuller exploration of the punctuation rules for text.
The language used in the source reads as if it were English aimed at a human reader (and this is intentional: the designer, after all, is a human reader and needs to be able to understand his or her own source), but in reality Inform can only understand a very modest range of sentences and will complain if its limits are passed. Subtler problems arise if the source contains contradictions. For instance, the following "Problem" might be produced:
, but in another sentence 'A Panama hat is on the cup'
: the trophy cup cannot both contain things and support things, which is what you're implying here. If you need both, the easiest way is to make it either a supporter with a container attached or vice versa. For instance: 'A desk is here. On the desk is a newspaper. An openable container called the drawer is part of the desk. In the drawer is a stapler.'This is a rather discursive error message, and if a similar problem were to occur in the same run through, it would be curtailed to:
, but in another sentence 'A fedora hat is on the box'
: again, the croquet box cannot both contain things and support things.Inform provides for us to organise the source code in just the way that a printed book would be organised: with headings and subheadings. Firstly, we can put the title at the top. If the first paragraph consists only of a single quoted piece of text, then that's the title; and an author can also be given, as follows:
We will later see that more bibliographic information can also be placed here, in the same way that the imprint page of a novel comes before the text gets going. The author's name can normally be given without quotation marks, so long as it contains no punctuation. For instance:
needs quotes as otherwise the full stop after the K will be mistaken for the end of a sentence.
A sentence which is the only one in its paragraph and which begins with any of the words "volume", "book", "part", "chapter" or "section" is considered to be a heading or a sub-heading. It must not contain a typed line break, and in order to stand alone in its paragraph there should be a skipped line both before and after it. For instance:
Headings can be written in any format, provided they start with one of the five indicator words, and they are hierarchical: a "Part …" heading is considered more significant than a "Chapter …" heading but not so significant as a "Book …" heading, and so on. (We do not need to use all five kinds of heading.)
Reports of problems, as we have seen, often quote back the source to justify themselves. Rather than quoting line numbers ("Midsummer Day, line 2017" or something similar) Inform uses the
icon. The down side of this is that a glance at the list of problems might give little hint of whereabouts in the source the difficulties lie. Inform therefore makes use of headings to give a general indication:
, but in another sentence 'South of the Attic is the Old Furniture'
: this looks like a contradiction, which might be because I have misunderstood what was meant to be the subject of one or both of those sentences.
, but in another sentence 'South of the Dark Room is the Cupboard'
: again, this looks like a contradiction.Secondly, headings are used in the Contents page of the Index, and they allow rapid navigation through the source, by jumping to any heading or subheading with a single click.
Finally, headings are used when working out what a name refers to. Suppose the source contains both a "four-poster bed" and also a "camp bed", and we write something like "The pillow is on the bed." Inform decides which bed is meant by giving priority to whichever is defined in the current section (so far), or failing that the current chapter, or current part, or current book, or finally the current volume. This allows us to write, for instance,
and not have the pillow mysteriously turn up on the camp bed, which hasn't been mentioned since way back in Chapter 2.
Problem messages are generated when the source text does not make sense to Inform. Even if it does make sense, though, there is no guarantee that it does what the author intends, and the only way to find out is to test the result by playing through it (or asking others to). For the most part one plays as if one were the eventual reader of the work, but sometimes it is highly convenient to have the god-like powers which are an author's prerogative. These are provided by the testing commands, which are present at every stage until the final release version (generated by the Release button). They will be introduced in this manual as they become relevant: here is the first.
The testing command SHOWME prints out a brief summary about a room or thing, and any contents or parts it may have. Typing SHOWME on its own shows the current room, but any item or room in the story, however distant, can be named instead. For instance:
Much of this can be seen, and seen more easily, in the World tab of the Index panel: but that only shows the initial state of play, whereas the SHOWME command reveals the situation in mid-story. ("Room", "supporter" and so on are kinds, of which more in Chapter 3.)
High-level debugging commands for more convenient testing commands like this one.
The only way to thoroughly test a work of IF is to run a complete solution through it, and carefully check the resulting transcript of dialogue. The Skein and Transcript tools of the Inform application are provided for exactly this purpose.
All the same, most works of interactive fiction contain occasional vignettes, either in terms of short scenes of narrative, or in the behaviour of particular things or rooms, which we would like to test without the fuss of using the full story-level Skein tool. The examples in the documentation are like this: in almost every example, typing TEST ME puts the story through its paces.
Solutions or sequences for testing ("scripts") can be defined with sentences like so:
This has no effect on the design itself, but ensures that when the story is played, typing "test balloon" will run through the given three commands in sequence, as if we had typed "get balloon" and then "blow balloon" and then "drop balloon".
The name for the test (balloon in this example) has to be a single word. Typing just "test" at the story prompt gives a list of all the test scripts known to the story. Test scripts can make use of each other, for instance:
One convenient way to keep track of the solution for a work being written is to include a test script at the end of each section, and to place a master test script (like "test all") at the top of the source. But different designers will prefer different approaches, and this testing system is no more than an optional convenience.
Many tests will only be sensible in given places, which may be hard to reach from the initial position; or with the aid of given things, which may be difficult to obtain. We are therefore allowed to add stipulations to test scripts:
The "… holding the balloon" means that the balloon will be transferred to the player's ownership immediately before the test script is run, unless it is already held. Similarly:
Or we might want to say both:
(Single quotation marks in test scripts are interpreted the same way in test scripts as they are in other text: that is, they are sometimes read as double-quotes unless they appear to be present as apostrophes. The notation ['] forces a single quotation mark if necessary. Similarly, [/] forces a literal forward slash, and prevents the / from being read as dividing up two commands.)
Sometimes when testing it's convenient to get hold of something not easily available at the moment. The testing command "PURLOIN" does this:
This can also make test scripts shorter, but of course it's important to make sure that people without PURLOIN powers can still play through.
Special testing commands, like "TEST" and "SHOWME", are automatically excluded from the story if it is exported from the Inform application using the Release button. We sometimes want to write our own for-testing-purposes-only code, though, and for this purpose we are allowed to designate whole headings as being "not for release":
Clearly we do not wish the final reader to be able to type "OPEN SESAME", so this whole heading will be disregarded in the Release version, as will any heading whose name includes "not for release".
Note that if a chapter, say, is marked as "not for release", then its subheadings (mere sections) will also not be for release. If in doubt, check the "Contents" index: if any section is "not for release" then so are all of its subheadings.
The reverse effect is produced by:
That is, it marks material included only in a Release version.
The original Inform of 1993 provided no special facilities for "extensions" – in effect, additional packets of rules providing extra features – but the creation and circulation of these extensions soon became a flourishing part of Inform culture. Today's Inform actively promotes sharing of such extensions, both to bring writers together and to support good practice. For the user of an extension, the advantage is clear: why go to great trouble to (say) work out how to make doors open automatically as needed, when somebody else has already perfected this? For the writer of an extension, there is the satisfaction of producing a good solution to a ticklish problem, and contributing to the public good.
Newcomers will probably not need extensions for quite some while, but there is nothing difficult about using them, so a few brief notes are worth giving here. (The final chapter of the documentation covers the writing of new extensions.)
Extensions are identified by name (say "Following People") and also by author (say "Mary Brown"). They need to be installed before they can be used, which means downloading them from the Internet. By far the easiest way to do this is to use the Public Library feature of Inform: then the application can do everything, letting us either choose individual extensions or download them en masse. But it's also possible to install extensions by hand.
In fact, though, Inform can automatically install extensions for us: we need only select the "Install Extension…" item on the File menu.
The actual extension file should always be named with a ".i7x" suffix, meaning "I7 extension" – for instance, "Following People.i7x".
To provide an example, Emily Short's useful extension "Locksmith" is one of a small number of extensions which come ready-installed as part of the basic Inform package, and need not be downloaded and installed.
Each time that Inform translates any source text, it performs a quick check of the extensions available, and updates its own internal records. A directory of the extensions currently installed can be found by clicking on "Installed Extensions" from the Extensions panel. This is also worth visiting in order to browse the Public Library, a selection of extensions contributed by Inform users.
We talk about "including" such an extension into a work of IF because the process merges rules and behaviours from the extension with those we have described ourselves. It's not uncommon for contributions by five or six different people to be pooled together this way.
Including an extension is only a matter of writing a single sentence in the source. For instance:
Note that it is compulsory to name both extension and author.
Many extensions come with their own documentation. Again, follow the "Installed Extensions" link to see what's available from them.
One more preliminary. Inform has a small number of optional settings which affect the result of translating the source. The sentence:
makes the resulting work of IF use American spellings (except where the designer spells otherwise) and the American convention for spelling out numbers (thus, "one hundred seventeen" not "one hundred and seventeen"). Similarly:
uses a comma when printing lists: thus "Julian, Dick, George, and Anne" rather than "Julian, Dick, George and Anne". A more profound change is made by
which introduces the concept of a numerical score – something which modern authors of interactive fiction often feel is inappropriate, which is why Inform only provides it on request. Two alternative options:
change the normal way room descriptions are shown: normally they are given in full, but in abbreviated mode, they're never given. (The latter is a bad idea in any publicly released story, but is provided for completeness and in case it may help testing.) Alternatively, we can set the traditional Infocom-style of room description to any of VERBOSE, BRIEF and SUPERBRIEF:
The default is now VERBOSE, but until 2010 it was BRIEF.
Next we have:
which disables the UNDO verb, both in play and after death, for the benefit of stories which are heavily randomised and where we do not want players to keep on UNDOing until they get a random outcome which is to their taste. (Many players consider UNDO to be their birthright, and that any work using this option is an abomination: indeed, it has even been suggested that this section of the Inform documentation be censored. To use the option is to court controversy if not outright hostility.)
We can combine any number of options in a single "Use" sentence, so for example:
brings about both of these changes.
Inform is increasingly used in education, where teachers sometimes need to install it on a whole room of computers at once, and want to monitor their students' progress. There is no special "classroom" version of Inform, but a couple of small administration features in the standard Inform – usually never needed – might be helpful to teachers.
When Inform starts up, it now looks for a file called Options.txt inside the user's home folder for Inform. (On Mac OS X, this is "~/Library/Inform"; on Windows, "My Documents\Inform", and so on.) If the file is present, then the text in it is added to the source text of everything Inform translates.
This must be used only to set use options, specify test commands, and give release instructions. For example, the following is a valid "Options.txt":
The idea is that this file can be used for setting up a standard configuration on multiple machines in a classroom setting. Here the instructor can make sure the Release button will do what she would like, and can arrange for each student's copy of Inform to respond to given Test commands: for instance, if the class has an assignment to create a simulation of a camera, the instructor could set up "Options.txt" so that TEST CAMERA would run through some commands the camera ought to respond to.
A new use option, "Use telemetry recordings.", causes Inform to copy its outcome and problem messages to files in its home folder (see above) as they occur. These files are dated, so that for instance
contains all of the recorded activity on 25 March 2009. Telemetry only records the contents of the "Problems" panel – notes of success or failure, and problem messages – and nothing is transmitted via any network, so it isn't really surveillance. The user can deliberately add a note to the current telemetry file by writing something like this in source text:
(This is a way to make a note for the benefit of someone who will read the telemetry file – for instance, to comment on a problem message that has just appeared. Note the double-quotes. Otherwise, it's meant to look like the standard way that beta-testers mark up IF transcripts.)
These two features have been added in response to requests from education users. Let's suppose that Mr Lebling, who teaches 5th grade in Minnesota, wants to set things up just right for his class. He installs Inform on the ten computers they will use, and also copies an Options.txt file from his memory stick onto each one. The Options.txt file reads:
Now Mr Lebling's class won't be confronted with English spellings, and so on. And most of the kids are happy, but Mr Lebling gets the feeling that young Marc wasn't really paying attention, so after class he checks that day's Telemetry file for that computer to see what Marc was up to, and whether he was stuck on something.
No computer has unlimited capacity, and a large, complex project may eventually bump its head against the ceiling.
Inform is a system for translating textual descriptions of interactive fiction into "story files". No single format of story file is standard to the IF community. The formats developed over the history of IF differ in three key respects:
Inform can write to two different formats. Neither of these is proprietary, and neither was created by the authors of Inform: each format is a community property, defined by published standards documents. An individual Inform project can make its own choice of story file format, using that project's Settings panel. Outside the Inform app, Inform can even be used at the command line to generate C programs rather than story files, and those can be compiled to run on almost any computer.
Newly created projects are set up with the Glulx format. This has largely taken over from an earlier format called the Z-machine, but Inform can still generate a version 8 Z-machine file (a so-called "z8") if required. The Z-machine is of historic importance, and may continue to be useful for certain tasks where Glulx support is not yet available, but most users will want to keep the Glulx format set all of the time.
Internally, the Inform application uses a tool called Inform 6 (which was once the entire Inform system) as the final stage in manufacturing the story file. Inevitably, though, this can go wrong if the story is so large or complex that it exceeds some fundamental limitation of the current story file format. This is only likely to happen with the Z-machine format, since Glulx has a huge capacity; so the cure here is to switch to Glulx in the Settings. But if that's not possible for some reason – say, if we want a story file playable on a tiny handheld computer unable to manage Glulx – we still have a few options. Unless the story is very large (in which case there is little we can do), the "z8" format is most likely to be exhausted for lack of what is called "readable memory", with a message like so:
followed by a tabulation of how the Z-machine's storage has been used, a large but not very useful diagram. The first time one runs into the problem on a large project, it can be postponed, by adding the following to the source:
(Economy cuts down the verbosity of some of the testing commands, but otherwise subtracts no performance.) Writing this into the source is the equivalent of a diver switching to an emergency oxygen tank: it gives us a generous safety margin, but also tells us that now is the time to wrap things up.
If we hit the problem again, genuine cuts must be made. As a general rule, the most memory-expensive ingredients of an Inform design are various-to-various relations between large kinds such as "thing" or, if there are many rooms, "room". Other than that, if a kind has been festooned with new properties and we have created dozens of items of that kind, then we can get a fairly large saving simply by doing without one of those properties; and so on.
The ultimate memory-saving device, of course, is the one used by book publishers when there are too many pages to bind: to cut the design into two stories, Part I and Part II.
All software has bugs, and Inform is no exception. The most obvious bugs are the ones which Inform catches itself, when it confesses that it has halted in failure, or translated the source text into a program which cannot be compiled further. But sometimes it will also happen that Inform will issue a misleading Problem message, or appear to work normally but to produce a story which does not do what it should have done.
It is very helpful for users to report faults, so that the program can be improved for everyone else. To report a fault, please first check with the Inform home page to make sure that the version of Inform you have used to detect the fault is the latest version available. You can find the latest versions at
If the bug is still present in the latest version, please report the bug using Inform's bug tracking database. Links for this can be found from the Inform source code page:
It may be that someone else has already identified the bug and even that a workaround for users is suggested. If not, please make an account at the bug tracking system and submit the requested information to help Inform's maintainers track and fix the fault.
No. No computer does, and Inform does not even try to read the whole wide range of text: it is a practical tool for a particular purpose, and it deals only with certain forms of sentence useful to that purpose. Inform source text may look like "natural language", the language we find natural among ourselves, but in the end it is a computer programming language. Many things which seem reasonable to the human reader are not understood by Inform. For instance, Inform understands
but not (at present, anyway)
even though both are perfectly good English. So it is not always safe to assume that Inform will understand any reasonable instruction it is given: when in doubt, we must go back to the manual.
More philosophically, to "understand" involves contextual knowledge. Just because Inform recognises and acts on a sentence, does it really understand what we meant? It will turn out that Inform is both good and bad at this. For instance, from
Inform will correctly deduce that Darcy is a person, because inanimate objects do not ordinarily wear clothes, and that the top hat is clothing. But it will not automatically know that Darcy is a man rather than a woman because it does not know the social convention implied by "Mr". Moreover, if instead we had written
then Inform would not guess that the top hat is clothing. This is because it does not have the vast vocabulary and experience of a human reader: it is probably discovering the word "hat" for the first time.
Finally, it is best to avoid ambiguities rather than rely on Inform to know which meaning is patently absurd. For instance, in
(a headline once printed by the Oxford Mail newspaper) a human reader quickly realises that there is no clog hospital being broken. But if Inform had been taught the verbs to break and to clog then that is exactly the conclusion it would have drawn. Or an example which genuinely arose in beta-testing:
in which Inform construed the verb as support and not fits, and then created items called "the life" (plural) and "unit fits the egg".
That disclaimer completes the groundwork, and we are ready to begin on simulating a world to explore.
At its simplest, the interactive fiction will be simulating a physical world to explore. The forerunner of today's IF is generally agreed to be a computer simulation by Will Crowther of the exploration of a cave system in the Mammoth and Flint Ridge chain of caves in Kentucky, a part of which might be described in Inform thus:
Here we sketch in four of Crowther's locations, and two objects: just enough to be able to walk around the caves and pick up the rod and the cage. The text in quotation marks will appear verbatim as paragraphs shown to the player as the caves are explored. The first paragraph, as we have seen, is the title of the work. The other quotations describe the places and objects introduced.
If we play this story, we find that we can type TAKE CAGE or TAKE WICKER CAGE, for instance, but not TAKE SMALL CAGE. Inform saw that we called this "a wicker cage" when it first appeared in the source text, and assumed that the player would call it that, too. (Whereas it didn't look inside the descriptive text to allow for TAKE SMALL CAGE or TAKE DISCARDED CAGE or TAKE NEARBY CAGE.) A small limitation here is that probably only the first 9 letters of each word are read from the player's command. This is plenty for handling the wicker cage and the black rod, but it might be embarrassing at a meeting of the Justice League to find that KISS SUPERHERO and KISS SUPERHEROINE read as if they are the same command.
So we have already found that Inform has made some assumptions about what we want, and imposed some limitations on how much computational effort to go to when the work of IF is finally played. If Inform guesses what we need wrongly, we need to know more advanced features of the language in order to overcome these problems. (We shall see how to change the way the player's commands are read in the chapter on Understanding.)
This is often how Inform works: make the standard way of doing things as simple as possible to describe, but allow almost any behaviour to be altered by more elaborate source text. As an example of that, the player begins in the Cobble Crawl because it was the first room created in the source text, but we could instead have written text like:
to override that. This can make the source text easier to follow if the rooms are sometimes being created in a less obvious way. For example, if we write:
then the first room to be created will actually be the Y2 Rock Room, so that's where the player will be starting unless we say otherwise.
Rooms are joined together at their edges by "map connections", most of which are pathways in one of the eight cardinal compass directions: north, northeast (written without a hyphen), east, southeast, south, southwest, west, northwest. We also have up and down, suitable for staircases or ladders. In real life, people are seldom conscious of their compass bearing when walking around buildings, but it makes a concise and unconfusing way for the player to say where to go next, so is generally accepted as a convention of the genre.
Two more directions are provided by Inform: "inside" and "outside". These are best used when one location is, say, a meadow and the other is a woodcutter's hut in the middle of it; we might then say
The "from" is important, as it clarifies that we intend to link two different locations, not to create an item – the hut – in a single location – the meadow.
A problem which sometimes arises when laying out maps is that Inform allows short forms of room names to be used as abbreviations. This is usually a good idea, but has unfortunate results if we write:
…because "Airport" is taken as a reference to "Airport Road", so Inform makes only two locations, one of which supernaturally leads to itself. We can avoid this by writing:
Using "called" is often a good way to specify something whose name might give rise to confusion otherwise. It always makes something new, and it is also neatly concise, because we can establish something's kind and name in the same sentence. As another example, suppose we want to create a room called "South of the Hut", to south of the Hut. We can't do so like this:
…because Inform will read that first sentence as placing a (nameless) room to the south of a room called "Hut". Once again "called" can save the day:
It is best to use "called" in the simplest way possible, and in particular, best not to use "called" twice in the same sentence. Consider:
It is unlikely that anyone would want to name something "a mixing bowl and a portable supporter called a platter", but not impossible, and Inform tends not to be a good judge of what is likely.
(If we really want to get rid of this issue once and for all, starting the source text with the use option "Use unabbreviated object names." will do it, but the effect is drastic. This instructs Inform not to recognise names other than in full. For example:
is ordinarily read by Inform as constructing three rooms (Kitchen, Roaring Range, Pantry); but with this use option set, it makes four (Kitchen, Roaring Range, Range, Pantry), in two disconnected pieces of map. Handle with care.)
Connections are ordinarily two-way, but do not have to be. One of the map connections in the Mammoth Cave simulation was made by the sentence:
Besides reading this sentence at face value, Inform also deduced that the Crawl was probably meant to be east of the Debris Room: in other words, that the path between them is a two-way one. When Inform makes guesses like this, it treats them as being less certain than anything explicitly stated in the source. Inform will quietly overturn its assumption if information comes to hand which shows that it was wrong. That might happen in this case if another sentence read:
These two sentences are not contradictory: Inform allows them both, simply accepting that the world is more complicated than it first assumed. There are relatively few situations where Inform has to make educated guesses, but when it does, it tries always to follow Occam's Razor by constructing the simplest model world consistent with the information in the Source text.
We can even explicitly make a route which turns around as it leads between two rooms:
If we want to establish a route which cannot be retraced at all, we can specify that a particular direction leads nowhere:
Finally, note that Inform's assumptions about two-way directions are only applied to simple sentences. When the source text seems to be saying something complicated, Inform takes it as a precise description of what's wanted. So, for example, in:
Inform makes guesses about the first sentence, and makes a two-way connection; but it accepts the second sentence more precisely, with just a one-way connection.
Rooms represent individual places to which one can go, but we tend to think of the world around us in larger pieces: we think of a house and a garden, rather than each of the single rooms of the house and all corners of its garden. To Inform a collection of rooms is called a "region", and we can create one like so:
The real usefulness of creating regions like "Public Area" will only appear later, when we begin defining rules of play which apply in some areas but not others, but in the mean time we can see the effect by turning to the World tab of the Index. In the World Index, Inform draws a map – or at least a stylised attempt at a diagram of the rooms and their connections: this will not always correspond to how we imagine things, but with any luck it should mostly be right.
Rooms are represented by coloured squares, and the colour-coding is done by region. In the above example, the two "Public Area" rooms are coloured green (as it happens); the Greenhouse, since it belongs to no region, is a neutral grey.
Regions can be put inside each other:
but they are not allowed to overlap other than by one being entirely inside the other.
Improving the index map for ways to adjust the way the index map is drawn or exported for publication.
The following description runs to only 33 words, but makes a surprisingly intricate design. It not only places things within rooms, but also places them very specifically with respect to each other:
Inform needs to identify the places and objects being described by the nouns here, and to guess what it can about them. For instance, the pistol can be picked up but not walked inside, whereas the Treehouse is the reverse. (This is obvious to someone who knows what these words mean, less obvious to a computer which does not, but the text contains sufficient clues.) Inform does this by sorting the various nouns into different categories, which are called "kinds". For instance:
(A container is something which can contain other things, and a supporter similarly.) For instance Inform knows that if one thing is in another, then the second thing is either a room or a container, and if one thing is on another, the second thing is a supporter. This worked nicely for the design above, but:
results in the cardboard box being made only a "thing": because nothing has been put inside it, there is no reason for Inform – which does not know what a cardboard box looks like – to guess that it is a "container". So we need to add:
It is rather clumsy to have to write two sentences like this, so we would normally write this instead:
Some containers, like bottles, can be opened: others, like buckets, cannot. If they can be opened, then sometimes they will be open, and sometimes closed. These are examples of properties, which can change during play. The following source sets some properties:
There are only four different properties referred to here. Closed means not open, and vice versa, so these two adjectives both refer to the same property. (As might be expected, when a container is open, one can see inside and place things within, or take them out.) The glass bottle and the box being containers is a matter of their kinds, which is something fundamental and immutable, so "container" does not count as a property.
A "transparent" container is one which we can see inside even when it is closed, and the opposite is an "opaque" container.
The property of being "fixed in place" ensures that the player cannot pick the item up and walk away with it: this is useful for such things as oak trees or heavy furniture. The opposite condition is to be "portable".
A container which is "openable" can be opened or closed by the player; as might be expected, the opposite is "unopenable".
With a really large cardboard box, we might imagine that the player could get inside: such a container should be declared "enterable".
Properties depend very much on kind. It makes no sense to ask whether a room is transparent or opaque, for instance, so Inform will not allow this either to be specified or queried.
Another way that kind influences properties can be seen from an earlier example:
The cup, the pistol and the table are all allowed to have the "fixed in place" property, but in fact only the table actually has it: the cup and the pistol are created as "portable" instead. This is because Inform knows that most things are portable, but that supporters – such as the table – are usually fixed in place. If this assumption is wrong, we need only add the line:
As we have just seen, making something "fixed in place" will prevent it from being picked up or moved. But it remains substantial enough to be described in its own paragraph of text when the player visits its location. This can be unfortunate if it has also been described already in the body of the main description for that location. For instance, if we wrote:
This would end up describing the oak twice, once in the paragraph about the Orchard, then again in a list of things within it:
We avoid this by making it "scenery" instead of "fixed in place":
Any thing can be scenery, and this does not bar it from playing a part in the story: it simply means that it will be immobile and that it will not be described independently of its room. Being immobile, scenery should not be used for portable objects that are meant to be left out of the room description.
If a supporter is scenery, it may still be mentioned in the room description after all, but only as part of a paragraph about other items, such as
If the player takes the candlestick and the Times, the teak table will disappear from mention. (Scenery containers do not behave in this way: their contents are assumed to be less immediately visible, and will be mentioned only if the player looks inside them.)
It is a cardinal rule that nothing can be in more than one place at the same time, but rules were made to be broken, and an exception is allowed for a special kind of thing called a "backdrop". For instance:
Backdrops are ordinarily in the background: if the sky needed to be referred to in the course of play, it might be represented by a backdrop, for instance. Here we have a stream of water running through two rooms, though it might be any number. Backdrops are always fixed in place.
Backdrops can be put in regions as well as rooms, and if so, then they are present at every room in the given region (or regions), as well as any specific rooms they may also be put into. For instance:
The special place "everywhere" can be given as the location of a backdrop to make it omnipresent:
Inform assumes that backdrops are also scenery unless told otherwise, so this will not result in messages like "You can also see the sky here." being included in room descriptions. In the case of the stream above, we could artfully mention it in passing in the room descriptions of the Upper Cave and the Rock Pool.
Moving backdrops for ways to place backdrops in dynamically changing selections of rooms.
The properties we have seen so far have all been either/or: either open or closed, either transparent or opaque, either fixed in place or portable, either openable or not openable. However, some properties can have a much wider range of possibilities. For instance, the "description" of a room is the text revealed when the player first enters it, or types "look". This needs to be textual: Inform would complain if, for instance, we tried to set the description of something to the number 42. We have already seen a concise way to set the description of a room:
This does the same thing as:
Or even:
The player's first sight of something is the text used as its "initial appearance":
This text appears as a separate paragraph in the text describing the Painted Room. It will continue to be used until the first time player picks the ring up (if this ever happens), so it normally describes things in their original, undisturbed context. (Inform uses an either/or property called "handled" for this: something is "handled" if it has at some point been held by the player.)
Thus when a piece of text stands alone as a sentence in its own right, then this is either the "description" of the most recently discussed room, or the "initial appearance" of the most recently discussed thing. Either way, it is used verbatim as a paragraph in the text shown to the player visiting the room in question.
But a thing also has an ordinary "description", which is used to give a close-up look at it. This text is ordinarily only revealed to the player when a command like "examine ring" is keyed in:
Creating a scene for the description of a scene, which is set in the same way.
The map of an interactive fiction is the layout of rooms and the entrances and exits which connect them. So far, these map connections have always run from one room to another, like so:
However, we can also interpose doors between rooms, like so:
The second sentence is needed since otherwise Inform will take "heavy iron grating" to be the name of a third room, whereas what we want is for the grating to be something physically present in both the Orchard and in the Undertomb, and acting as a conduit between them. To this end it needs to be a "door", a kind we have not so far seen. In the absence of any other instruction, a newly created door will be fixed in place, closed and openable.
The grating really does come in between the two rooms: the grating is what lies immediately east of the Orchard, not the Undertomb room. So if we wrote the following:
then Inform would say that this is a contradiction: we said the Undertomb was east of the Orchard, but then we said that the grating was east of the Orchard.
Inform's "door" kind can be used for all manner of conduits, so the word door need not be taken literally. In Ursula K. Le Guin's beguiling novel "The Tombs of Atuan", from which the above rooms are stolen, it is not a grating which interposes, but:
In real life, most doors are two-sided, and can be used from either of the rooms which they join, but this is not always convenient for interactive fiction. Here is a one-sided door:
(Note the use of "it" here as an optional abbreviation.) This will make a door visible only on the Notting Hill side; no map connection will be made in the reverse direction, unless we ask for one.
So much for creating and describing individual doors. Once we need to write about doors in general, we are likely to want a way to find out where a given door sits in the map. The following phrases reveal this:
This phrase produces the first of the one or two rooms containing a door – first in the order given in the source text. Example: if
then "front side of the red rock stair" produces the Orchard. For a one-sided door, this produces the only room containing the door.
This phrase produces the last of the one or two rooms containing a door – last in the order given in the source text. Example: if
then "back side of the red rock stair" produces the Undertomb. A one-sided door has no "back side."
More often, we are dealing with a door and want to know what it leads to, but that depends where we're standing:
This phrase produces the room on the other side of the door, as seen from the given vantage point, which needs to be one of its sides. Example: if
then "other side of the red rock stair from the Undertomb" produces the Orchard, and vice versa.
This phrase produces the direction in which the door leads, as seen from the given vantage point, which needs to be one of its sides. Example: if
then "direction of the red rock stair from the Undertomb" produces up.
Adjacent rooms and routes through the map for more phrases which can look at the current map layout.
It seems unwise for a door in Notting Hill to be unlocked, so:
Since the second sentence here is a little clumsy, we can equivalently say
Yet a third way to say this is:
This introduces three new properties: a door can be locked or unlocked; lockable or not lockable; and it can have a matching key, which must be another thing. The same thing can be the matching key of many different locks: and note that a door can be locked and even lockable without having a matching key at all, in which case the player trying to open it will be permanently out of luck. Doors are ordinarily unlocked, not lockable, and without a matching key.
Containers can also have locks, in exactly the same way, and are allowed to have the same properties. On the other hand supporters never have locks: it makes no sense to be able to lock a tabletop, for instance, and Inform will not allow any discussion of the matching key of a supporter, or of a supporter being locked or unlocked.
A "device" is another of the standard kinds of thing, and should be used for anything which can be switched on or off: a light switch, say, or a slide projector. Devices are generally machines, clockwork or electrical. A device is always either "switched on" or "switched off", but is switched off unless we specify otherwise.
That makes three kinds of thing which will likely change their appearance according to which of their two possible states they are in: doors and containers, which can be open or closed; and devices, which can be switched on or switched off. We would like to produce text accordingly, and we can do this using Inform's ability to make (almost) any piece of text change with circumstances. For instance:
We could use a similar trick to make the appearance of a device change "if switched on". There will be much more about text substitutions, as instructions in square brackets like these are called, in later chapters.
Text with substitutions for more on varying what is printed.
Rooms can be "dark" or "lighted", though they are lighted by default, and are lighted in all the examples we have seen so far.
When the player is in a dark room, he can still go in various directions, but he cannot see the room description or interact with any of the objects in the room, except those he is holding. This means that, unless we should change the Cave in some way during play, the text above ("A profoundly…") will only be read if the player succeeds in bringing light into the Cave, perhaps by bringing along the following:
A thing with the property of being "lit" will enable the player to see inside dark rooms, and to carry out other activities requiring light, such as examining items. A lit thing in an open container will still light up a room; a lit thing in a closed container will not, unless the container has been given the "transparent" property.
It is possible to adjust the way darkness behaves, and we will see more on this topic in the chapter on Activities.
Printing a refusal to act in the dark for the first of several ways to control what is printed in the dark.
Next in the tour of standard kinds is the "vehicle". This behaves like (indeed, is) an enterable container, except that it will not be portable unless this is specified.
The player can enter the sports car and then move around riding inside it, by typing directions exactly as if on foot: and the story will print names of rooms with "(in the red sports car)" appended, lest this be forgotten.
We have already seen that some things are portable, others fixed in place. In fact we can also make a third sort of thing: those which, although not portable, can be pushed from one room to another with commands like "push the wheelbarrow north". At a pinch, we might just be willing to allow:
But of course this is a property which almost any thing can have, not just a vehicle. (Only "almost" because Inform will not allow a door to be pushable between rooms, in the interests of realism rather than surrealism.)
If we need vehicles which the passenger sits on top of, like a horse or a tractor, the standard "vehicle" kind will not be ideal. However, by loading one of the extensions which comes ready-installed:
…we are provided with two more kinds, "rideable vehicle" and "rideable animal", just right for the tractor and the horse respectively. (As with all extensions, the documentation can be seen by clicking Go on some source which contains the above line, and then turning to the Contents index; or from the Installed Extensions tab of the Extensions panel.)
Going by, going through, going with for further ways to customize vehicle behaviour.
Rounding out the standard kinds provided by Inform are four for living things: "person", which is a kind of thing, and "man", "woman" and "animal", all kinds of person. For instance:
For the time being, men and women will be little more than waxworks: they will come to life only when we go beyond the present stage of creating an initial state of the world.
People can be male or female: this is an either/or property for the "person" kind, and it affects play at run-time a little, because the player can use "him" and "her" to refer to male or female people encountered. Men and women are always male and female respectively, and for animals we can choose either way, for example making a stallion male or a nanny goat female. Animals are male unless we say otherwise.
If our animal is instead something like a beetle or an earthworm, where gender doesn't seem to matter or even to exist, we can use the further property "neuter":
The Standard Rules don't make people behave differently according to their genders, and the main difference comes down to language: whether we want the animal to be called "her", or "it". Because of the existence of "neuter", we sometimes need to be cautious about the use of the adjective "male": since Inform, partly for historical reasons, uses an either/or property for masculinity, neuter animals are also "male".
Suppose we have said that:
When the Ballroom is visited, the man is listed in the description of the room as "Mr Darcy", not as "a Mr Darcy". This happened not because Inform recognised that Darcy is a proper name, or even because men tend to have proper names, but because Inform noticed that we did not use "a", "an", "the" or "some" in the sentence which created him. The following shows most of the options:
In the resulting story, we read:
The subtlest rule here is in the handling of "the". We wrote "The bell is in the Belfry", but this did not result in the bell always being called "the" bell: in fact, writing "A bell is in the Belfry" would have had the same effect. On the other hand, "A woman called the sexton's wife is in the Belfry." led to the wife always being known as "the" sexton's wife, not "a" sexton's wife, because Inform thinks the choice of article after "called" shows more of our intention than it would elsewhere. These rules will never be perfect in all situations, so we are also allowed to specify indefinite articles by hand, as the vicar's case shows.
"Some" is worth a closer look, because English uses it in several different ways. By introducing the woodworm with "some", above, we established that it was plural. We might imagine that there are many worms, even though they are represented by a single thing in Inform. We can expect to see text in the story such as:
But suppose we wanted something which there is an amount of, but which is not made up of individual items – a so-called mass noun like "water", or "bread". Now we can write:
and this time Inform does not treat the "some water" thing as a plural, so we might read:
rather than "The water are hardly portable."
Finally, we can override these settings, if they still come out not as we intend, by explicitly changing the either/or properties "singular-named" (vs "plural-named") and "proper-named" (vs "improper-named").
The containers and supporters created so far have been boundlessly capacious: or rather, though we seldom notice the difference, have had a maximum carrying capacity of 100 items. This is clearly unrealistic for a small purse or a modest mantelpiece. We can impose upper limits with sentences like so:
Attempts by the player to overfill, or overload, will now be rebuffed with a message such as "There is no room on the mantelpiece".
The player is not a container or a supporter, but nevertheless does have a carrying capacity: this is interpreted to mean the maximum number of items which can be carried at once.
These restrictions only apply to the player (and other in-world characters): as the omnipotent creators, we are not restrained by them. Nothing prevents this:
The player will be able to remove all three items, but only put two of them back. (This is probably something we only want very occasionally: perhaps to create a sack stuffed almost to bursting point.)
We have seen how to place objects in rooms, and in containers or on supporters. But what about people? Perhaps it could be said that they "contain" the fillings in their teeth, or "support" a top hat, but this is not very natural. Inform therefore never speaks of things being "in" or "on" people. Instead, they have two sorts of possessions: the things they carry, and the things they wear. (Body parts, such as arms and legs, are different again: see "parts" below for a clue to how to do these.) Thus:
In fact, Inform deduces from this not only who owns the hat and the sword, but also that Darcy has the kind "person", because only people can wear or carry.
As all the assertion verbs do, "to wear" and "to carry" have participles which Inform knows about. So we could equally well write:
If we do not specify who does the wearing, or carrying, then this is assumed to be the player. Thus:
It would make no sense to "wear" the key, for instance, so Inform needs to distinguish between what is clothing and what is not. It does this with an either/or property called "wearable": if something has this property then the player will be allowed to wear it, provided it can first be picked up. Anything which is worn by somebody at the start of play is assumed to be wearable (unless we say otherwise). But if nobody is initially wearing the item in question, then we have to be explicit:
(When we come to asking questions about the current situation, we will need to remember that "to carry" and "to wear" are different. Thus "if Lancelot carries the plate armour" will not be true if he is wearing it rather than carrying it under his arm. As we will later see, we can instead vaguely say "if Lancelot has the plate armour" to mean either carrying or wearing.)
To carry, to wear, to have for a more detailed explanation of carrying, wearing, and possessing as Inform understands them.
When the player has only limited carrying capacity, play is likely to be tiresome, but we can make life easier by providing a way for the player to carry endless items without dozens of free hands to hold them all:
This example story introduces a new kind of container, the "player's holdall". This is a kind of which most stories will contain at most one example, but in principle there can be any number. A player's holdall is a capacious bag into which the player automatically places surplus items whenever his or her hands are full: trying the above example story and getting the items one by one will give the general idea.
Of course, if the carrying capacity of the player is never reached then there will never be any surplus items and a player's holdall will behave just like any other (portable, usually openable) container.
Units for the tools to implement a more sophisticated capacity system.
We have nearly reached the end of the chapter on Things, but one either/or property for things remains: every thing is either "edible" or "inedible". Unless we say otherwise, things are inedible. But for instance we might write:
(The type of computer is named after a variety of apple descended from a tree cultivated in 1811 by John McIntosh of Ontario.) Edible things are just like inedible ones, except that the player can EAT them. This will usually only consume the foodstuff in question, effectively destroying it, but using techniques from later chapters we could make the consequences more interesting.
Everything has one and only one kind. This is both good and bad: good for clarity, bad if something needs to behave in two different ways at once. How might we simulate a car with an ignition key, given that no single thing can be both a "vehicle" and a "device" at the same time?
The Inform world model takes the view that such a car is too complicated to be simulated with a single thing. Instead it should be simulated as a vehicle (the car) which has a device (the ignition) attached. This is done using a third kind of containment to those seen so far ("in…" and "on…"): "part of".
The machine and the desk each have several "parts" representing subsidiary pieces of themselves. The desk is a "supporter" (it needs to be, for the liquorice twist to be on top) but also has three "containers" attached, each of which can be opened or closed independently.
In the interests of realism, the standard rules of play protect these composite things. Thus if the desk were to be moved elsewhere (rolling on sugar casters perhaps) then its parts would move with it, and the player is not allowed to detach parts of things: the drawers can be opened or closed, but not pulled out altogether.
Note that rooms and regions are not allowed to have parts. (Rooms are already parts of regions, and to divide up rooms, we can either make several rooms or place containers or other obstacles in a single one.)
Though realism can become tiresome in interactive fiction, there are times when we cannot go along with Inform's normal assumption that all of a person's possessions are visible to everybody else. People are not like containers, which either show all of their holdings or not, according to whether they are open or transparent. If a man is carrying a fishing rod and a wallet, one will be on open show, the other not. Some clothing is outwardly visible, but not all.
Whether or not something is concealed is not like the either/or properties we have seen so far – such as being "open" or "closed" – because it is not really a property of the thing itself, but depends on the habitual behaviour of its current owner. To talk about behaviour we have to use sentences of a kind not seen so far, and which will not fully be explained for some chapters to come.
But straightforward cases are easy to write, if only by imitating the following examples.
Here we make the Cloaked Villain invariably conceal anything she is holding or wearing:
At which point we think about it more carefully, and then rewrite:
(A rule which says neither "yes" nor "no" will decide yes, but it's best to spell out exactly what's wanted.)
Parts are treated exactly as if clothes or items being held, and the following will make the face and inscription on a coin invisible unless the player is holding it – the idea being that they are too small to be seen from farther away.
There is also an either/or property called "described"/"undescribed", intended to be used only as a last resort, but which has the ability to hide something from room descriptions. This not really hiding: the idea is that "undescribed" should be used only for cases where some other text already reveals the item, or where its presence is implicit. Even then, it should only be used when the item is intended to be taken or moved by the player at some point – if the item isn't intended to move, it's much better to make it "scenery". (There's only one commonly-found example – the player's own body, the "yourself", is undescribed.)
Note that the "undescribed" property is automatically removed from anything carried by, worn by or part of the player, even indirectly; and that nothing on top of an "undescribed" supporter will be visible in a room description, even if it itself is "described". (Scenery supporters don't suffer from that restriction, which is one reason scenery is a better option when possible.)
The model world created by Inform is partitioned into rooms. This means that everything which exists in the model world, exists in one of the rooms. If we write a sentence such as
and say nothing more about Wilderspin, then he does not physically exist at the start of the story: he is said to be "out of play", and stays that way until we move him into one of the rooms. A better metaphor might be that he is waiting in the wings, ready to come onto the stage.
Every thing is either out of play, or can be found in one of the rooms, and the property "location of X" gives us the room in question. The following condition tests, in effect, whether Wilderspin is in play:
Which uses a new phrase:
This phrase produces the room which, perhaps indirectly, contains the object given. Example: if the player stands in Biblioll College and wears a waistcoat, inside which is a fob watch, then
is Biblioll College. In general, a thing cannot be in two rooms at once, but there are two exceptions: two-sided doors, present on both sides, and backdrops. The "location of" a door is its front side, but a backdrop has no location. (Objects which are not things at all, such as rooms and directions, also have no location.)
We very often want to know the location of the player, and this is more simply called just "the location". (This is actually a value that varies rather than a phrase, but that's a technicality we can ignore here.)
The idea of indirect containment is useful enough to have a name: Inform calls it "enclosure". A thing encloses whatever is a part of itself, or inside itself, or on top of itself, and it also encloses anything that they enclose. And when something moves around, anything it encloses will move with it. In the example above, Biblioll College (a room) and the player (a person) both enclose the fob watch and the waistcoat. (The small print: a door is enclosed by the rooms on both sides; a backdrop is never enclosed.)
Enclosure is only useful when being used as a question. So the following is fine:
But these will produce problem messages:
because they are too vague. Inform needs to know exactly where the fob watch and the trilobite will begin the story, whereas these sentences leave room for doubt about who or what is actually holding them.
"Direction" is a kind which is quite unlike most of those seen so far. While it has to do with the physical world, a direction does not exactly belong to it. One cannot find "southeast" sitting on a shelf. "Direction" is not a kind of thing, nor a kind of room: it is a kind in its own right.
Every direction has an "opposite" property, which is always another direction. These occur in matched pairs. The opposite of north is south, just as the opposite of south is north. The opposite of southeast is northwest, the opposite of inside is outside, and so on. When Inform reads a sentence like…
…it assumes that the opposite map connection is probably also valid, so that
The chapter began with the twelve directions built into Inform:
But the built-in set is not always appropriate. Sometimes this is too many; if we wanted to write about a Flatland, for instance, then up and down ought to go. But in practice it is better not to abolish them as directions but instead to forbid travelling in them. (See the Recipe Book for examples.)
But away from our familiar Earth, the usual frame of reference loses its meaning. Terry Pratchett's "Discworld" comedies, set on a rotating disc, use the directions turnwise, widdershins, hubwards and rimwards. On board a Zeppelin airship, which constantly changes its course, the cockpit has no fixed compass bearing from the passenger cabin: it is not very naturally "north". In zero gravity, there is no up or down. Mars does not have a magnetic core, so a compass doesn't work there.
New directions must always be created in opposing pairs, and each must be declared with a clear simple sentence of the form "X is a direction." For instance:
It is then possible to write, say, that:
Of course the Map page of the Index for the project normally draws a map based on compass bearings, so it will get a little befuddled by this. But the map drawn in the Index can be given hints to improve its legibility. More on this later, but for now note that
maps turnwise directions as if they were east, that is, pointing rightwards on the page. (This has no effect on the story file produced; it does not mean turnwise is simply a new name for east; it affects only the look of the Index map, which is only a convenience for the author in any case.)
At one time, directions had to have shortish names (up to three words only), but that's no longer true:
Values are to Inform what nouns are to English sentences. They represent numbers, times of day, pieces of text, places, people, doors, and so on. Because they have such an enormous variety, and because we often want to talk about what some of them have in common, we need a way to sort all of these different ideas out. That's the main aim of Inform's concept of "kind".
Every value has a kind. The kind of 10 is "number"; the kind of 11:30 PM is "time"; the kind of "jinxed wizards pluck ivy from my quilt" is "text"; and so on. The Kinds index panel shows the kinds present in the current Inform project, which will always include a wide range of built-in kinds, and usually also some new ones created in that project.
Some kinds are more general than others. For example, if we write:
then Growler is an "animal", which is a kind of "thing", which is a kind of "object". When we talk about "the" kind of Growler, we mean "animal", the most specific one, but actually he belongs to all of those kinds.
As we see from this example, kinds have a whole hierarchy. Some are specialised versions of other kinds; some are not. Browsing the Kinds index shows that Inform builds its model world out of "objects". (That's really what objects are: "object" is a kind of value used to make the ingredients of the model world.) The objects fall into four fundamental kinds, "room", "thing", "direction" and "region", and "thing" is more subdivided still.
All the same, Inform starts out with a fairly simple arrangement. Because taxonomy – setting up kinds for everything – is so difficult, and depends so much on what you want it for, Inform creates relatively few kinds in advance: it has "animal" built in, but not "mammal" or "Bengal tiger". When we need more, we must make them ourselves. Let's see how we might invent these new kinds. The easy one is:
Given that, we can then write:
That's easy enough. Adding "mammal" now looks awkward, though, because it seems to belong in between the two. All Bengal tigers are mammals, but not all animals are. But Inform can sort this out:
If we look at the Kinds index, we should indeed see a hierarchy:
though the diagram is laid out as a sort of tree, just as zoologists do.
As another example, it may seem curious that Inform doesn't usually think "man" is a kind of "animal". This is really because, in English, people don't usually expect something like "if an animal is in the garden" to be true when it's only the Revd Mr Beebe going for a walk. People expect the word "animal" not to mean a human being, despite our common genetic ancestry. But if we want to rearrange Inform's default ideas, we can do that quite easily:
Or indeed we could say:
While this is an ideal way to make new kinds for the model world, we are more restricted in what we can do outside of objects. For instance,
isn't allowed. The numbers are fixed and all exist already; they aren't like Bengal tigers which we can simply imagine, and fill the world with. "Number" is not a concept we can specialise any further. But what we can do is to invent entirely new concepts, like so:
We will see more of these later. (This isn't specialising anything – "value" is a sort of everything-category, and is too big and vague to be a kind.)
This seems a good point to see what we can do with new kinds. Here we invent a new kind to provide a new sort of room:
Any dead end that we make is also a room, so it has all of the properties and behaviour of a room. For instance, every room is either "lighted" or "dark", and the default is to be lighted. But we can reverse that convention for dead ends, and we can also fill in some other properties:
As a result of this, three different rooms adjoin the Undertomb, all dead ends. This is much more concise than spelling them out one at a time would be.
Inform often doesn't mind in what order it is told about the world, but it may need to know the name of a kind before that kind can be used. For example,
makes sense to Inform and results in the creation of a new thing, just called "coffer" in the absence of any other name to give it, whose kind is "coffer" and which is initially open. Whereas if Inform reads:
without knowing that "coffer" is a kind, it simply makes a thing called "open coffer" (and which is not a container). Inform has to be careful like this: English is simply too overflowing with multiple meanings. An "open railway ticket", for instance, is not a "railway ticket" that one can put objects into.
When we write:
we are saying that it will be dark rather than lighted unless we should specify otherwise. So it would be fine to add:
because although dead ends are usually dark, this one is evidently an exception. On the other hand, if we had originally written
then Inform would not have permitted any exception to be made, and would have reported a problem if we had tried to make the Tortuous Alcove lighted. Besides "usually" and "always", we can also employ "seldom" and "never", which are their negatives. Thus, "never lighted" means the same as "always dark".
As the following examples show, sentences can make several assertions at once by using the plural. Suppose we have defined a kind called "high-up fixture", for instance like so:
Then the following sentence creates two such objects and puts them in their place:
since it is equivalent to saying:
Such plurals are allowed in almost any context, and we could even define two kinds at once:
Inform constructs plurals by a form of Conway's pluralisation algorithm, which is quite good – for example, it gets oxen, geese (but mongooses), sheep, wildebeest, bream, vertebrae, quartos, wharves, phenomena, jackanapes and smallpox correct. But English is a very irregular language, and multiple-word nouns sometimes pluralise in unexpected ways. So we sometimes need to intervene:
We are allowed to define more than one plural for the same singular text, and for the names of things, rooms or kinds, all alternative versions will be used interchangeably. (For instance, Inform defines both "people" and "persons" as plurals of "person".)
So much for making new and more specialised kinds of object – for example, new kinds of room, or new kinds of animal. This allows us to describe the physical world in elegant ways, but what about concepts which aren't so physical?
Without getting into philosophy, we can probably agree that numbers like 1, 2, 3, …, and texts like "Jackdaws love my big sphinx of quartz", are not physical. Inside Inform, those are values, but not objects. Inform already has a good stock of this sort of concept built in, so it may not immediately seem clear why we need to create new ones. But in fact this is very useful. To describe the physical world, we need concepts like (for example) distance and brightness. We want to say that two armchairs are 12 feet apart, or that a given light-bulb is very dim. Here, "twelve feet" and "very dim" are clearly not physical objects; they need to be values, but not objects.
As these two examples suggest, sometimes we want a quantitative way to measure things, sometimes not. Thomas Hardy, in his novel "The Return of the Native", writes:
Hardy doesn't tell us that the wavelength of the light is 700nm, he tells us that the colour is "lurid red", and we understand. Later in the same chapter, Hardy writes:
and now we do have a quantitative measurement: thirty feet. This is how people write about the world, and how they read about it. So Inform needs to provide both sorts of measurement.
(a) Here is a qualitative example. Suppose we would like a candle lantern to burn down, gradually diminishing in brightness. Then we'll need a way to talk about the current strength of the flame, but only in vague terms. Here goes:
"Brightness" is now a kind of value on a par with (for instance) "number" or "text". There are only four possible values, named as above. Kinds of value like this, where there are just a few named possibilities, are extremely useful, as we'll see.
(b) Now a quantitative example:
The difference here is not the way we create the kind, but the way we tell Inform what the possible values are. Instead of a list, we teach Inform some notation. As a result, "26kg" is now a value, for instance. Quantitative kinds like this are sometimes called "units", because – as in this example – they're often units in the sense of measuring things. Many Inform projects never need units, but they can still be very useful, and they're described in detail in the chapter on "Numbers and Equations".
So now we have seen two fundamental ideas: "value" and "kind". We have seen how to make a source text which refers to many values – for example, Growler the Bengal tiger, 23kg, "Collapsed Dead End", blazing, 7, all values of different kinds.
But we don't just want a way to refer to values, we want to lay out facts about them. Inform understands two sorts of fact, which it calls properties and relations. Properties are about single values in isolation: Growler is male. Relations are about how values interact with each other: Growler likes Bambi. (Or would like to eat Bambi, anyway.) Relations are really the central organising idea of Inform, and we've seen them many times already:
expresses a relation called "containment" between Growler and the Savannah. Much more about this in the chapter on Relations: for now, let's go back to the simpler idea of properties.
In Inform terms, a "property" is any fact about a value (other than its kind) which the author is allowed to choose. For example,
The first of these sentences talks about Growler's kind, but the other two sentences tell Inform about his properties. Properties are divided into either/or properties – "male" versus "female" – and value properties – such as the description of something, which can be any text.
The Kinds index shows which kinds of object are allowed to have properties. Every object is, so there's no problem with Growler. In general, if Inform can find a sensible way to store properties, then it will allow them. But it won't allow (for example) properties of numbers. There are only a finite number of Bengal tigers in the world (fewer than three thousand, alas), so Inform can easily store individual description texts for each one of them. But there are an infinite range of numbers. (Inform does allow adjectives like "even" or "odd" to be used about number – saying "if 7 is odd" is fine, for example – but they are not properties in the Inform sense, because the author doesn't get to choose. The author can choose whether Growler is a male or female tiger, but not whether 7 is an even or an odd number.)
Properties can't be handed out completely freely. In the previous chapter, we saw that we were allowed to make a chair "portable" and to make a room "dark". But if we try this the other way round, Inform produces a Problem message. This is because every property must be created in a way which lays out what values are allowed to have it. The Standard Rules built into Inform say that
and as a result it won't allow "The Savannah is portable" because the Savannah is a room, not a thing.
We must do the same. To go back to our example "dead end" kind:
This creates just one new property, not two. The names are taken as the two states of a single either/or property: secret means not ordinary, ordinary means not secret. Alternatively, we could just say:
in which case the opposite of "secret" would be "not secret".
Now we have a property which can be given to any value of the kind "dead end". We're also free to add to the definitions of kinds which already exist, including those built into Inform: for instance,
If we make the above definitions then all dead ends will be "ordinary" and all rooms "outdoors" unless the source text says otherwise. That is, in the absence of other information it's assumed that an either/or property is not true. We could reverse by writing:
A property can be used by several kinds at once. For example, the built-in either/or property "open" is used by both doors and containers, even though door isn't a kind of container and container isn't a kind of door. In fact, although it's more usual to declare properties for whole kinds, they can actually be given to single values one at a time, if we like:
And now the umbrella, which is a thing and not a door or container, can also have the property.
So much for either/or properties. Now we move on to properties which have values attached. The same principles apply, but the wording is different. For example,
The property "river sound" is now applicable only to dead ends, so we would not be allowed to talk about "the river sound of the Savannah", say. Moreover, it's required to hold a piece of text. If we tried the following:
…then Inform would object, because the number 7 is the wrong kind of value to go into the "river sound" property. If we need a numerical property, we can try this instead:
Suppose that we were to add:
The Defile must have a river sound, of course, because we said that every dead end would have one. We haven't said what that river sound will be, but Inform can work it out, because we did say this:
If there are no instructions at all about the value of a property, Inform fills in the default value of the appropriate kind – in this case, it would be a blank text. (A table of the kinds which can be used for properties, and their default values, can be found in the Kinds index.)
It turns out to be very useful to create a new kind of value, and then create a property to hold it. So useful, in fact, that Inform provides two shortened forms for doing so. Here is the first, and the second (making "conditions") is in the section following.
Suppose we go back to our example of the candle lantern whose brightness we have to measure. It's clear that what we want to do is to define:
And now we can use the technique of the previous section:
This works very nicely. The "flame strength" property is now only allowed to have one of four values we allowed: guttering light, weak light, radiant light or blazing light. So we have succeeded in recording our measurement.
But it seems artificial to call the brightness of the lantern "flame strength", when we could instead simply call it "brightness". Much simpler to write:
Now "brightness" is the name of both the property and the kind of value. What's particularly nice is that we can now use the names of the possible brightnesses – "weak", "blazing" and so on – as adjectives. Inform knows that "The lantern is blazing" must be talking about the brightness property, because "blazing" is a brightness.
Now we can improve our dead ends:
The "[brightness of the lantern]" is printed not as literal text, but as whatever the brightness currently is. (The square brackets mark it as what is called a text substitution, which will be the subject of the next chapter.) So we get something like this:
So now we have a lantern, which has a brightness as a property. But we can build on this further if we like. A brightness such as "guttering" is a value, so it can have properties in its own right. That can be quite useful, in fact:
This is convenient because it divides up the brightnesses:
And while we're at it, let's give each brightness its own corresponding temperature:
(Candle flames are hotter than most people think.)
Text with substitutions for more on varying what is printed.
Now for an even more abbreviated way to create a new kind of value, and at the same time create a property to hold it. Suppose we have something, say a wine cask, which we know is always in one of three different states. We can write:
This is just like our example of the lantern having possible brightnesses, but it's quicker to do, because we don't need to create or name the kind of value. (The trade-off is that we can't use it for anything else as well.)
Initially the cask will be "customs sealed", the first value we gave. We could now write, for instance,
Or, as a second example, here we're going to allow a whole kind to have the property, not just a single object:
Now in fact these properties are not anonymous: Inform has worked out names for them, even though we didn't give any. The usual arrangement is that the name is the name of the object with the word "condition" tacked on: for instance, "cask condition". So we could write:
so that sometimes this would be "wine cask (liable to tax)", sometimes "wine cask (stolen goods)" and so on.
But only usually, because we might need to define several different conditions of the same thing, and then the names would collide. For instance, suppose we write:
This makes a property and a kind of value each called "fruit condition". But now suppose we add that:
This is a quite unrelated property – a fruit could have any combination of these two properties, in fact. Left to itself, Inform will call the second one "fruit condition 2", which isn't really ideal if we ever do need to refer to it in other source text. So we are also allowed to give these conditions names of our own choosing:
And now the resulting property and kind of value would be called "squishiness".
Just about every kind has a "default value". Inform needs this when it knows that something has to be a value of a given kind, but it hasn't been told what the value is. For example, in the previous chapter we saw that every thing has a "description" text, but we also created plenty of things without describing them. So if Inform reads
and it isn't told anything else about the pear, what should it set the description of the pear to?
The answer is that Inform knows the description has to be a value of the kind "text", so it uses the default value of "text". Not very interestingly, this is just the blank text "".
Being uninteresting is exactly the idea, of course. The default number is 0, for instance. (Default values are tabulated in the Kinds index.)
It's sometimes useful to be able to refer to the default value of a kind without having to spell out what this is (especially if the kind is something obscure, or we're trying to write a rule for an extension which has to work in situations we don't fully know about).
Produces the default value of the kind named. Examples:
produces the output:
because nine in the morning is the default time in Inform. If we have:
then "default value of brightness" is guttering, the first brightness created. When it comes to kinds of object, we sometimes have to be a little careful. For example,
is always going to be fine (it's always the first room created in the source text). But
would produce a Problem message if there were no vehicles in the world.
Sometimes a value important to the simulated world will not naturally belong to any thing or room, and should not be kept in a property. In fact, we have seen a value that varies already: "location", which holds the room in which the story is presently taking place. Here's how we might make a new one:
Or "which varies" would also be allowed, as would the more traditional computing term "variable":
A briefer way to do this is to use the word "initially", which alerts Inform to the possibility that the value will change in future:
This creates the variable and gives it an initial value all in one sentence.
It's not compulsory to give an initial value. If we do not, Inform will use the default value for its kind. (See the table in the Kinds index.) For example, writing just
will start it at the value 0, because that's the default value for numbers.
We can have variables of any of the kinds of value, including new ones, but should watch out for a potential error. If we write:
in a world which has no containers at all, Inform will object, because it will be unable to put any initial value into the receptacle variable. A similar complaint will be made if we write:
without ever having defined any colours. Something else we are not permitted is:
because the openness of a given container may change during play, so that the value in the variable might suddenly become invalid even though the variable itself had not changed.
As a final note on kinds, when Inform reads something like this:
it has to make a decision about the kind of "accursed one". Peter is a "man", so that seems like the right answer, but Inform wants to play safe in case the variable later needs to change to a woman called Jane, say, or even a black hat. So Inform in fact creates "accursed one" as an object that varies, not a man that varies, to give us the maximum freedom to use it. If we don't want that then we can override it:
thus telling Inform exactly what is intended.
It's sometimes useful to name even values which don't change. For example, suppose the story involves driving, and the same speed limit value comes up in many places. Rather than typing "55" (say) every time it comes up, we might prefer to write:
at the start of the source text, and then talk about "the speed limit" every time we would otherwise have typed "55". Just as the word "initially" alerts Inform that we want the named value to change during play, the word "always" tells it that we don't.
This might seem pointless, because "speed limit" only means the same thing as "55" and takes more typing. But there are two reasons why authors might want to use this feature anyway. One is that it's easier for a human reader to understand the significance of a line like:
Another is that it makes it easier to change our minds about the value, because if we decide we want 70 as the limit and not 55, we only need to make one change at the start of the source text:
which is much easier than combing through a long source text trying to find many individual things which need changing.
"Speed limit" is then a number constant. Any attempt to set this elsewhere, or change its value, will result in a Problem message, and moreover it can be used in contexts where only constant values are allowed. For example,
means that the SHOWME TREVOR testing command produces, among other data:
Although it is only useful to a limited extent, we can make any number of copies of something:
The description "three triangles" makes three identical things, each of the kind "triangle", and similarly for the squares. When the above is compiled, the player can type TAKE TWO TRIANGLES or TAKE ALL THE TRIANGLES and so forth.
Four caveats. Firstly, a counted-out description like "two squares" is only allowed if it combines a number with the name of a kind which is already known (perhaps modified with adjectives, so "two open doors" is fine). If we say:
without having defined "circle" as a kind in advance, then only a single object will be created – whose name is "two circles". (This is because many natural names start with numbers: "six of clubs", for instance, referring to a single playing card, or "12 Hollywood Close" meaning a single house. We wouldn't want such names to be misinterpreted.)
The second caveat is that excessive duplication is expensive in memory and running time. It is perfectly legal to say
but the resulting story may be a little sluggish: and Inform draws the line at 100, refusing to create more duplicates than that in any single place. If we really need more than about fifty duplicated objects – say, a tombola containing raffle tickets numbered 1 to 1000 – it is usually better to find some less literal way to simulate this: for instance, only having a single raffle ticket, but with a randomly chosen number on it.
If there are very many items in the same place, commands like TAKE ALL and DROP ALL may mysteriously not quite deal with all of them – this is because the parser, the run-time program which deciphers typed commands, has only limited memory to hold the possibilities. It can be raised with a use option like so:
(The default is, as above, 100. Note the "at least".)
Thirdly, note that Inform's idea of "identical" is based on what the player could type in a command to distinguish things. In a few cases this can make items unexpectedly identical. For example:
results surprisingly in "You can see two chemicals here", because the run-time system truncates the words that are typed – POLYETHYLENE and POLYETHYLENE-TEREPHTHALATE look like the same word in a typed command. So Inform decides that these are indistinguishable chemicals. Typically words are truncated after 9 letters, though (unless the Glulx setting is used) punctuation inside a word, such as an apostrophe, can make this happen earlier. The best way to avoid trouble is simply to use more easily distinguishable names. For example:
works fine, because now only one chemical can be called TEREPHTHALATE, and that means they can be distinguished.
Finally: numbers up to twelve may be written out in words in the source text, but larger ones must be written as numerals. So "twelve" or "12", but "13" only.
In the previous chapter, we saw that it was possible to make sub-parts of things. For instance,
creates a door with an attached handle. But what if we want to say that not just this door, but every door, should have a handle? To do this we first need to create a kind called "handle", since there will clearly need to be many handles. The solution is:
"Every" is a loaded word and best used sparingly. A sentence like "A handle is part of every handle" would, if taken literally, mean that a handle takes forever to make and is never finished. Inform will reject this, but the moral is clear: we should think about what we are doing with "every".
We will usually want to work with smaller collections – not literally every room, but with a whole set of them all the same. We can do that like so:
The effect of sentences like these is to make what we might call "assemblies" instead of single things. When a banking room is created, so are five more silver coins; when a door is created, so is another handle. Such sentences act not only on items created later on in the source text, but also on all those created so far.
This is especially useful for body parts. If we would like to explore Voltaire's suggestion that history would have been very different if only Cleopatra's nose had been shorter, we will need noses:
Of course, if we make an assembly like this then we had better remember that the player is also a person and also gets a nose. In fact slightly odd things can happen if we combine this with changing the identity of the player. This works:
but if those lines are in reverse order then Cleopatra's nose is assembled before she becomes the player, with the result that it ends up called "Cleopatra's nose" rather than "your nose" in play – which is very regal but probably not what we want. To avoid this, settle the player's identity early on in the source text.
All of the assemblies above make objects. Most make these new objects "part of" existing ones, but as we saw, they can also be "in" or "on" them. In fact, though, assemblies work in much more general ways: they can assemble values of almost any kind, placed in almost any relationship. To make use of that, we need to create a new verb, a topic which won't be covered properly until a later chapter, but here goes:
Now every time a person is created, so is a colour which that person will like. If there are two people in the world, the player and Daphne, then we now have five colours: red, green, blue, Daphne's colour and the player's colour. Alternatively, we can assemble the other way around:
Now we're telling Inform that every time a colour is made, a new person is also made – someone who will like that colour. So this sentence effectively makes three new people, one who likes red, one who likes green, and one who likes blue.
Something skated over in the previous section is the question of how Inform gives names to objects (or other values) it creates in an assembly. The standard thing naming combines the names of what's being assembled. For example:
might result in the creation of "Antony's nose", part of Antony, and "Cleopatra's nose", part of Cleopatra. In this way, Inform names the noses after their owners. It will always do this unless there are multiple indistinguishable things being created, as in the "five silver coins are in every banking room" example: those will all just be called "silver coin".
A small pitfall of this is that if we write:
then although "Marcus Tullius Cicero's nose" and "Cicero's nose" are both valid names for the consular nose, "Marcus's nose" is not.
The standard naming scheme is often about right, but as usual Inform offers a way to improve it in particular cases. For example, if we write:
then we will find the world full of, say, the Garden buggy, the Patio buggy and so on – instead of the Garden vehicle, the Patio vehicle and so on, which is what we would have had without the "called…" part. Similarly, we could write:
The former would produce new people with names like "Green's fan", whereas the latter would produce new colours with names like "Daphne's favourite colour".
So much for an informal description. Here is exactly what Inform does:
(The reason that (2) doesn't affect objects is that objects are allowed to have names clashing with other objects, or no name at all, whereas other values have to have names belonging to themselves alone.)
That concludes our tour through the design of the initial state of a simulated world. We have seen how to create rooms and to stock them with containers, supporters, devices, doors, men and women. The player of such a simulation can explore, move things around, open and close certain doors and containers, lock or unlock them provided a suitable key is found, switch machines on or off, and so on.
But that is about all. There is as yet no element of surprise, no aim or sense of progress to be earned, and no narrative thread. We have painted the backcloth, and laid out the properties, but the actors have yet to take the stage.
In the previous chapter, we gave properties to certain kinds of things in order to change their appearance and behaviour, and saw brief glimpses of one of Inform's most useful devices: text substitution. The following gives a more complete example:
The novelty here is the text in square brackets in the first paragraph. They imply more or less what they would when a journalist is quoting something in a newspaper article. The actual words "river sound" are not part of the text. Instead, when Inform prints up the description of a dead end, it will substitute the appropriate river sound in place of these words.
Thus the description of the Collapsed Dead End is "This is a dead end. You'll have to go back the way you came, consoled only by a faint whispering of running water.", whereas the description of the Tortuous Alcove is "This is a dead end. You'll have to go back the way you came, consoled only by a gurgle of running water." As the player explores these dead ends, subtle differences will appear in their room descriptions.
Text is so fundamental to Inform that the basics had to be covered back in Chapter 2, so let's begin this new chapter with a recap.
Literal text is written in double-quotation marks. It's mostly true that what you see is what you get: the literal text "The Hands of the Silversmith" means just
But four characters are read in unexpected ways: [, ], ' and ". The rules are as follows:
Exception 1. Square brackets [ and ] are used to describe what Inform should say, but in a non-literal way. For example,
might produce
These are called "text substitutions". They're highly flexible, and they can take many different forms. But as useful as they are, they do seem to stop us from making actual [ and ] characters come through on screen. To get around that:
This text substitution expands to a single open square bracket, avoiding the problem that a literal [ in text would look to Inform like the opening of a substitution. Example:
prints as "He [Lord Astor] would, wouldn't he?".
This text substitution expands to a single close square bracket, avoiding the problem that a literal ] in text would look to Inform like the closing of a substitution. Example:
prints as "He [Lord Astor] would, wouldn't he?".
Exception 2. Single quotation marks at the edges of words are printed as double. So:
produces
This is good because typing a double quotation mark inside the quote wouldn't work – it would end the text then and there. Single quotation marks inside words, such as the one in "it's", remain apostrophes.
The rule looks odd at first, but turns out to be very practical. The only problem arises if we need an apostrophe at the start or end of a word, or a double inside one. Again, substitutions can fix this:
This text substitution expands to a single quotation mark, avoiding Inform's ordinary rule of converting literal single quotation marks to double at the edges of words. Example:
produces:
A more abbreviated form would be:
which has exactly the same meaning.
This text substitution expands to a double quotation mark. Most of the time this is unnecessary because of Inform's rule of converting literal single quotation marks to double at the edges of words, so it's needed only if we want a double-quote in the middle of a word for some reason. Example:
which produces: The compass reads 41o21'23"E. (Note that ["] is not allowed; a double-quotation mark is never allowed inside double-quoted text, not even in a text substitution.)
Exception 3. Texts which end with sentence-ending punctuation – full stop, question mark, exclamation mark – are printed with a line break after them. So:
would come out quite differently – this doesn't affect the appearance of the text, but only the position where the next text will appear. Again, sometimes this is not what we want – the full rules are complicated enough to be worth a whole section later in the chapter.
We can put almost any description of a value in square brackets in text, and Inform will work out what kind of value it is and print something accordingly. (Only almost any, because we aren't allowed to use commas or more quotation marks inside a square-bracketed substitution.)
This text substitution takes the value and produces a textual representation of it. Most kinds of value, and really all of the useful ones, are "sayable" – numbers, times, objects, rules, scenes, and so on. Example:
Here "time of day" is a value – it's a time that varies, and time is a sayable kind of value, so we might get "The dial reads 11:03 AM."
The values we say most often are objects. If we simply put the name of what we want into square brackets, this will be substituted by the full printed name. We might find:
But this reads oddly – clearly "the" or "a" is missing. So the following substitutions are used very often:
This text substitution produces the name of the object along with its indefinite article. Example:
which might produce "You can only just make out a lamp-post.", or "You can only just make out Trevor.", or "You can only just make out some soldiers." The "a" or "an" in the wording is replaced by whatever indefinite article applies, if any.
This text substitution produces the name of the object along with its indefinite article, capitalised. Example:
which might produce "A lamp-post can be made out in the mist.", or "Trevor can be made out in the mist.", or "Some soldiers can be made out in the mist." The "A" or "An" in the wording is replaced by whatever indefinite article applies, if any.
This text substitution produces the name of the object along with its definite article. Example:
which might produce "You can only just make out the lamp-post.", or "You can only just make out Trevor.", or "You can only just make out the soldiers." The "the" in the wording is replaced by whatever definite article applies, if any.
This text substitution produces the name of the object along with its definite article, capitalised. Example:
which might produce "The lamp-post may be a trick of the mist.", or "Trevor may be a trick of the mist.", or "The soldiers may be a trick of the mist." The "The" in the wording is replaced by whatever definite article applies, if any.
This may not look very useful, because why not simply put "the", or whatever, into the ordinary text? The answer is that there are times when we do not know in advance which object will be involved. For instance, as we shall later see, there is a special value called "the noun" which is the thing to which the player's current command is applied (thus, if the player typed TAKE BALL, it will be the ball). So:
might produce replies like "You find a solid rubber ball.", "You find an ink-stained blouse.", "You find some elastic bands.", or even "You find Mr Polycarp." (the school's pet hamster, perhaps).
When a numerical value is given in a square-bracketed substitution, it is ordinarily printed out in digits. Thus:
might print as "You've been wandering around for 213 turns now.", if the story has been played out for exactly that many commands. But if we prefer:
This text substitution writes out the number in English text. Example:
might produce "You've been wandering around for two hundred and thirteen turns now." The "and" here is natural on one side of the Atlantic but not the other – so with the "Use American dialect." option in place, it disappears.
Either way, though, there is some risk of the following:
We can avoid this using the special substitution:
This text substitution prints a letter "s" unless the last number printed was 1. Example:
produces "… for one turn now." or "… for two turns now." as appropriate. Note that it reacts only to numbers, not to other arithmetic values like times (or, for instance, weights from the "Metric Units" extension).
This only solves one case, but it's memorable, and the case is one which turns up often.
We often want running text to include lists of items.
This text substitution produces a list, in sentence form, of everything matching the description. Example:
And, if this were from a dramatisation of the novel by Miss Fielding rather than Miss Austen, we might find:
If the description matches nothing – for instance, if Darcy has empty hands – then "nothing" is printed.
As with all lists in Inform, the serial comma is only used if the "Use serial comma." option is in force. So by default we would get "a fishing pole, a hook and a sinker", rather than "a fishing pole, a hook, and a sinker".
We then need variations to add indefinite or definite articles, and to capitalise the first item. For example,
might result in
This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its indefinite article. Example:
This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its indefinite article, and the first is capitalised, so that it can be used at the beginning of a sentence. Example:
This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its definite article. Example:
This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its definite article, and the first is capitalised, so that it can be used at the beginning of a sentence. Example:
So much for articles. A more insidious problem comes with something like this:
The trouble is that the list may end up either singular or plural. We might be expecting something like:
But if there is only one room, then the result might be:
which is wrong. We can get around this with careful wording and a slightly different substitution:
This text substitution produces a list, in sentence form, of everything matching the description. The whole list starts with "is" (if there's one item or none) or "are" (more than one). Examples:
This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its indefinite article, and the whole list starts with "is" (if there's one item or none) or "are" (more than one). Examples:
This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its definite article, and the whole list starts with "is" (if there's one item or none) or "are" (more than one). Examples:
This text substitution produces a list, in sentence form, of everything matching the description, noting any contents in brackets. This is really intended only to be used by the Standard Rules.
Text sometimes needs to take different forms in different circumstances. Perhaps it needs an extra sentence if something has happened, or perhaps only one altered word.
This text substitution produces no text. It's used only for a side-effect: it says that the text following should be said only if the condition is true. That continues until the end of the text, or until an "[end if]" substitution, whichever comes first. If the "[otherwise]" and "[otherwise if]" substitutions are also present, they allow alternatives to be added in case the condition is false. Example:
we find that the cask is described as "a broached, empty cask" when open, and "a sealed wine cask" when closed. A longer example which begins and ends with fixed text, but has two alternatives in the middle:
This text substitution produces no text. It's used only for a side-effect: it says that the text following should be said only if the condition is false. That continues until the end of the text, or until an "[end if]" substitution, whichever comes first. If the "[otherwise]" and "[otherwise if]" substitutions are also present, they allow alternatives to be added in case the condition is true. Example:
This text substitution produces no text, and can be used only following an "[if …]" or "[unless …]" text substitution. It switches from text which appears if the condition is true, to text which appears if it is false. Example:
This text substitution produces no text, and can be used only to close off a stretch of varying text which begins with "[if …]".
This text substitution produces no text, and can be used only to close off a stretch of varying text which begins with "[unless …]".
This text substitution produces no text, and can be used only following an "[if …]" or "[unless …]" text substitution. It gives an alternative text to use if the first condition didn't apply, but this one does. Example:
This text substitution produces no text, and can be used only following an "[if …]" or "[unless …]" text substitution. It gives an alternative text to use if the first condition didn't apply, and this one is false too.
We sometimes need to be careful about the printing of line breaks:
This room description has two possible forms: "Ah, the unknown cell. ", at first sight, and then "Ah, the usual cell." subsequently. But the second form is rounded off with a line break because the last thing printed is a ".", whereas the first form isn't, because it ended with a space. The right thing would have been:
allowing no space after "unknown cell."
When varying descriptions are being given for kinds of rooms or things, it can be useful to make use of a special value called "item described", which refers to the particular one being looked at right now. For example:
The tuba now has the description "An especially shiny, well-tuned tuba.", and similarly for the xylophone.
The "item described" value can similarly be used in any textual property of a room or thing, and in particular can be used with the "initial appearance" and "printed name" properties, which are also forms of description.
Sometimes we would like to provide a little quirky variation in text, especially in messages which will be seen often. We can achieve this with the "[one of]… [or] … [or] …" construction.
This text substitution produces no text. It's used only for a side-effect: it switches between a number of alternative texts, which follow it and are divided by "[or]" substitutions, according to a strategy given in a closing substitution. Example:
Here there are just two alternatives, and the strategy is "purely at random". Exactly half of the time the text will be printed as "You flip the coin. Heads!"; and the other half, "You flip the coin. Tails!".
This text substitution produces no text, and can be used only in a "[one of]…" construction. It divides alternative wordings. Example:
There are seven possible endings, each making the choice of which text to follow in a different way:
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are chosen uniformly randomly.
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are chosen in sequence until all have been seen, but that after that they are chosen uniformly randomly.
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are chosen at random except that the same choice cannot come up twice running. This is useful to avoid the deadening effect of repeating the exact same message. Example:
Here we can safely say the light "changes", because the new colour cannot be the same as the one printed the last time.
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are chosen in sequence until all have been seen, and then after that, at random except that the same choice cannot come up twice running. Example:
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that a random choice is made the first time the text is printed, but that it sticks from there on. Example:
Although the newspaper headline will change with each playing, it will not alter during play.
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are chosen at random, except that the first is most likely to be chosen, the second is next most likely, and so on down to the rarest at the end. Example:
There are six outcomes here: the first is six times as likely as the last, and those in between are similarly scaled, so Zorro cuts himself shaving only once in 21 tries, while he looks purposeful almost a third of the time.
But suppose we want to tuck some useful information in these messages, and we want to be sure that the player will see it. Because all of the above options involve randomness, it's possible that an unlucky player might miss a clue placed into only one variant of the message. One fix for this is to make sure that everything turns up sooner or later:
This text substitution produces no text, and can be used only to end a "[one of]…" construction. A random order is chosen for the alternative passages of text, and they are used in that order as the text is printed again and again. When one random cycle finishes, a new one begins. The effect is somewhat like the "shuffle album" feature on an iPod. Example:
One small restriction: if there are more than 32 variations, purely random choices will be printed, and there will be no guarantee that repeats are prevented.
Another fix is to avoid randomness altogether:
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are used one at a time, in turn: after the last one is reached, we start again from the first. Example:
This text substitution produces no text, and can be used only to end a "[one of]…" construction. It indicates that the alternatives are used one at a time, in turn: once the last one is reached, it's used forever after. Example:
Finally, here's a convenient shorthand for one of the commonest things needed:
This pair of text substitutions causes whatever is between them to be printed only the first time the text is printed. Example:
This is exactly equivalent to
but easier to read.
Something to watch out for is that texts are sometimes being printed internally for purposes other than actual output which the player can see, and this is particularly true of names. For example:
This looks good for some purposes, but may not cycle in the sequence expected, and can result in incorrect indefinite articles being printed -- "an red traffic signal", for example. What's happening is that the name is being printed internally to see whether it begins with a vowel; that prints "amber traffic signal", but invisibly to us, and since this does begin with a vowel, "an" is visibly printed; then the name is visibly printed, but now it has changed to "red traffic signal", and so the result on screen is "an red traffic signal". There are many ways to avoid this (for example, to give the traffic signal a state which changes every turn, not every time the name is printed), but it's a trap to look out for.
Inform controls the flow of text being said so that it will read, to the player, in a natural way. There are two principles:
(a) pieces of text ending with full stop, exclamation or question marks will be followed by line breaks (or "new lines", as some computer programming languages would call them); and
(b) pieces of text produced by different rules in Inform will be separated by paragraph breaks.
The effect is that authors can forget about paragraph spacing most of the time, but the mechanism is not impossible to fool, so text substitutions are provided to override the usual principles. First, to manipulate line breaks:
This text substitution produces a line break. Example:
Line breaks are not paragraph breaks, so the result is:
with no extra vertical spacing between these lines.
This text substitution produces no text. It's used only for a side-effect: it prevents a line break where Inform might otherwise assume one. Example:
Here the "[no line break]" stops Inform from thinking that the exclamation mark means a sentence ending – it's part of the name of the song "Rule, Britannia!". So we get
with no line break between the "!" and ".".
And similarly for paragraph breaks. Because Inform can be pretty trigger-happy with these, the first need is for a way to stop them:
This text substitution produces no text. It's used only for a side-effect: it prevents a paragraph break occurring after the present text is printed, in case Inform might be tempted to place one there. Example:
This allows the reply to, say, TAKE ENVELOPE to be
rather than
which is how texts produced by different rules would normally be shown. (It's a traditional printer's term. See Oldfield's Manual of Typography, 1892, under "When two paragraphs are required to be made into one, or, in technical language, 'to run on'.")
But sometimes we actually want paragraph breaks in unexpected places. One way is to force them outright:
This text substitution produces a paragraph break. Example:
Paragraph breaks have a little vertical spacing in them, unlike mere line breaks, so the result is:
More subtly, we can give Inform the option:
This text substitution either produces a paragraph break, or no text at all. It marks a place where Inform can put a paragraph break if necessary; in effect it simulates what Inform does every time a "before" or similar rule finishes. If there is text already printed, and text then follows on, a paragraph break is made. But if not, nothing is done. This is sometimes useful when producing a large amount of text which changes with the circumstances so that it is hard to predict in advance whether a paragraph break is needed or not.
Really finicky authors might possibly want to know this:
This condition is true if text has recently been said in such a way that Inform expects to add a paragraph break at the next opportunity (for instance when the present rule ends and another one says something, or when a "[conditional paragraph break]" is made).
Finally, there are two special sorts of paragraph break for special circumstances. They are mainly used by the Standard Rules, and imitate the textual layout styles of traditional IF.
This text substitution produces a line break, and then also a paragraph break if the text immediately following is a room description brought about by having gone to to a different room and looking around, in which case a line break should be added. In traditional IF, this is used when clarifying what Inform thinks the player intended by a given command. Example:
might result in
This text substitution produces no text. It's used only for a side-effect: it indicates that the current printing position does not follow a skipped line, and that further material is expected which will run on from the previous paragraph, but that if no further material turns up then a skipped line would be needed before the next command prompt. (It's very likely that only the Standard Rules will ever need this.)
Inform does not go in for the use of fonts: a work of IF will be rendered with different fonts on different machines anyway, from tiny personal organisers up to huge workstations. However, it does allow for a modest amount of styling.
This text substitution produces no text. It's used only for a side-effect: to make the text following it appear in bold face. "[roman type]" should be used to switch back to normal. Example:
This text substitution produces no text. It's used only for a side-effect: to make the text following it appear in italics. "[roman type]" should be used to switch back to normal. Example:
This text substitution produces no text. It's used only for a side-effect: to return to ordinary Roman type after a previous use of "[bold type]" or "[italic type]".
but there is one other effect we can employ:
This text substitution produces no text. It's used only for a side-effect: to make the text following it appear with fixed letter spacing. In variable letter spacing, a lower case "m" is much wider than an "l", which is natural to the eye since it has been printing practice since the Renaissance. Fixed letter spacing is more like typewriting, and it is best used to reproduce typewritten text or printed notices; it can also be convenient for making simple diagrams. Example:
This text substitution produces no text. It's used only for a side-effect: to return to ordinary letter spacing after a previous use of "[fixed letter spacing]".
Whichever effect we use, we should be careful to ensure that we return to normal -- roman type and variable letter spacing -- after any specially-treated text has been printed. Combining these effects (for, say, bold fixed-spaced lettering) is not guaranteed to work, though on some platforms it will.
Inform 7 is infused by the English language, so it's a challenge using it to write a work of IF in any other language. (With that said, extensions do exist which have made considerable progress on this problem: nil desperandum.) But even a book in English contains occasional quotations or words borrowed from other tongues, so we are going to need more than plain A to Z.
The world has a bewildering range of letters, accents, diacritics, markers and signs. Inform tries to support the widest range possible, but the works of IF produced by Inform are programs which then have to be run on a (virtual) computer whose abilities are more constrained: few players will have an Ethiopian font installed, after all. So a degree of caution is called for.
(a) Definitely safe to use. Inform's highest level of support is for the letters found on a typical English typewriter keyboard, including both the $ and £ signs (but not the Yen or Euro symbols ¥ and €), and in addition the following:
These characters can be typed directly into the Source panel, and can be used outside quotation marks: we can call a room the Église, for instance.
(b) Characters which can safely be used, but will be simplified. As it reads in the text, Inform silently converts all kinds of dash (en-rules, em-rules, etc.) to simple hyphens; converts the multiplication symbol to a lower case "x"; converts all kinds of space other than tabs (em-spaces, non-breaking spaces, etc.) to simple spaces, and all kinds of quotation marks to "straight" (non-smart) marks.
(c) Characters which can be used provided they are in quoted text (other than boxed quotations), and which will probably but not certainly be visible to the player. All other Latin letter-forms, including the œ ligature, East European forms such as ő, ş and ž, and Portuguese forms such as ũ; the Greek and Cyrillic alphabets, with their associated variants and accents; and the principal currency symbols, such as € and ¥. Such characters are not legal in unquoted text: so we could write
but not
Moreover, the player is not allowed to type these characters in commands during play: or rather, they will not be recognised if he does. They are for printing only.
(d) Characters which might work in quoted text, or might not. The Arabic and Hebrew alphabets are fairly likely to be available; miscellaneous symbols are sometimes legible to the player, sometimes not. Other alphabets are chancier still. (If a work of IF depends on these being visible, it may be necessary to instruct players to use specific interpreters, or to provide a way for the player to test that all will be well.)
As we have seen, Inform allows us to type a wide range of characters into the source text, although the more exotic ones may only appear inside quotation marks. But they become more and more difficult to type as they become more obscure. Inform therefore allows us to describe a letter using a text substitution rather than typing it directly.
Unicode characters can be named (or numbered) directly in text. For example:
produces a Polish slashed L. If the Unicode Character Names or Unicode Full Character Names extensions are included, characters can also be named as well as numbered:
The Unicode standard assigns character numbers to essentially every marking used in text from any human language: its full range is enormous. (Note that Inform writes these numbers in decimal: many reference charts show them in hexadecimal, or base 16, which can cause confusion.) Inform can only handle codes [unicode 32] up to [unicode 65535], so it is not quite so catholic, but the range is still enormous enough that code numbers are unfamiliar to the eye. Inform therefore allows us to use the official Unicode 4.1 names for characters, instead of their decimal numbers, provided we have Included the necessary extension like so:
This extension provides names for some 2900 of the most commonly used characters. It means, for instance, that we can write text such as:
Admittedly, these can get a little verbose:
But before getting carried away, we should remember the hazards: Inform allows us to type, say, "[unicode Saturn]" (an astrological sign) but it appears only as a black square if the resulting story is played by an interpreter using a font which lacks the relevant sign. For instance, Zoom for OS X uses the Lucida Grande and Apple Symbol fonts by default, and this combination does contain the Saturn sign: but Windows Frotz tends to use the Tahoma font by default, which does not. (Another issue is that the fixed letter spacing font, such as used in the status line, may not contain all the characters that the font of the main text contains.) To write something with truly outré characters is therefore a little chancy: users would have to be told quite carefully what interpreter and font to use to play it.
The "Unicode Character Names" extension, which is pre-installed in the standard distribution of Inform, defines names for the Latin, Greek, Cyrillic, Hebrew and Braille alphabets, together with currency and miscellaneous other symbols, including some for drawing boxes and arrows. It is only optionally installed because even this is quite large: but in case it should still prove inadequate, an alternative can be used:
This includes all 12,997 named characters in the 16-bit range of the Unicode 4.1 standard: it is the size of a small novel and its inclusion will slow Inform down. But if you want to experiment with Arabic, ecclesiastical Georgian, Cherokee, Tibetan, Syriac, the International Phonetic Alphabet, hexagrams or the unified Canadian aboriginal syllabics, "Unicode Full Character Names" (again built into Inform) is the extension for you.
Text is normally printed in between the typed commands of the player, rolling upwards from the bottom of the screen, as if a dialogue is being typed by an old-fashioned teletype. But it can also be displayed in a bolder way, floating above the main text, and this is sometimes used to display quotations.
This phrase displays the given text on screen in an overlaid box. For reasons to do with the way such quotations are plotted onto the screen, their text is treated literally: no substitutions in square brackets are obeyed. The quotation will only ever appear once, regardless of the number of times the "display the boxed quotation …" phrase is reached. Rather than being shown immediately – and thus, probably, scrolling away before it can be seen – the display is held back until the next command prompt is shown to the player. Example:
This was the original example used in Trinity, by Brian Moriarty, which invented the idea. A player exploring Kensington Gardens comes upon a location enigmatically called The Wabe; and by way of explanation, this quotation pops up.
Note that exotic accented characters, such as the "Ł" in "Łodz", can't be displayed in boxed quotations. This is only a simple feature, and we should go in search of a suitable extension for fancier screen effects if we would like to do more.
If we have some textual effect which needs to occur in several different messages, we might want to create a new text substitution for it. For instance:
This is only the tip of the iceberg in how to define ways to do things using "To…", as we shall see. The definition makes "say the security notice" a new phrase known to Inform. A text substitution is exactly a phrase whose name begins with "say" (well – except for the "say" phrase itself), so the effect is that "[security notice]" is a new text substitution. Several of the examples in this chapter make use of this trick.
Inform often ignores the casing of the text it reads, but sometimes uses it as a clue to meaning. We have already seen that "[an item]" and "[An item]" produce different results, for instance. Similarly, it's possible to define two text substitutions which are the same except for the initial casing. We might write:
And now Inform will act on "[Security Notice]" differently from "[security notice]".
The phrasebook for other forms of phrase besides To say....
It is in describing circumstances that Inform really capitalises on the concise, expressive power of natural language, and this chapter brings together the facts about "descriptions".
The simplest descriptions consist of a noun alone. Some refer to single things ("lantern", or "wine cask"), others to kinds of thing ("dead end" or "container"). But we have also seen adjectives alone:
Here, "fixed in place" is a description which, to Inform's simple-minded grammar, is a single adjective. And of course adjectives and nouns can be combined:
The description "openable container" consists of the noun "container", meaning a kind of thing, and the adjective "openable", which means one of the two possible states of an either/or property held by that thing.
As the next chapter will show, rules also make great use of descriptions:
We have already seen that we can list the items fitting a given description:
It's also sometimes convenient to count them up:
This phrase counts the number of values matching the description, which may of course be 0. Example:
produces the number of doors, anywhere in the model world, which are currently open. A Problem message is produced if the number is potentially infinite, or impractical to count: for instance, Inform rejects "number of odd numbers".
It is because descriptions are so widely useful that they deserve a chapter of their own, and this is it.
Descriptions can contain a noun, but need not, and can contain any number of adjectives:
Note that we are not allowed to have more than one noun in the same description (something English occasionally does allow as a coded form of emphasis, as in "the man Jenkins" or "the harlot Helen").
Nouns are simple enough, referring either to kinds or specific things. The noun "something" means "some thing", so is actually a reference to the kind "thing". Inform treats this as having the same meaning as "anything", and all told there are eight special nouns of this kind, but with only three different meanings between them:
So for instance "anybody male" or "somewhere dark" are valid descriptions. These eight nouns are unusual in being allowed to come at the front of a description: nouns are usually expected to be at the end. (Inform also understands "nothing", "nowhere", "nobody", "no-one" and even "no one", which in a sense are opposites of "something" and the like, but for now we'll look at descriptions of things which do exist rather than don't.)
We have seen two sorts of adjectives so far: those which refer to either/or properties, like "open" and "closed", and those which come out of new kinds of value. If we define
…then "rough", "stubbly" and "smooth" all become adjectives. (That last sentence "Everything has a texture" was essential, because without it Inform would not know that these words could meaningfully be applied to things.)
In addition to these adjectives, we can create new ones (as we shall see), and a few special adjectives such as "visible", "touchable" and "adjacent" are already defined for us by Inform.
Suppose we want to coin a word for supporters currently supporting something. We can do so with the following sentence:
Note the colon, which is essential, and the usage of "it" in the definition part to refer to the object in question. (For this purpose we would write "it" even if we were defining a term about, say, a woman instead of a supporter, so that "she" or "her" might seem more appropriate – but see below.)
This creates the adjective "occupied", and gives it a definition valid for supporters. That restriction on validity means that non-supporters would always fail the description "something occupied"; which might be unfortunate if we wanted to talk about rooms being occupied. We could give a second definition thus:
These are entirely different senses of the word "occupied" – a mantelpiece is occupied if an invitation is on it, but for a drawing room to be occupied there must be human presence – and Inform applies whichever sense is relevant when deciding whether or not a given object is "occupied".
Often, though not always, we also want to give a name to the opposite possibility. We can do that as follows:
The "rather than…" part of the definition is optional, but it saves having to write a boringly similar definition of "unoccupied" out in longhand. (Note that Inform does not guess the meaning of "unoccupied" unless it has been explicitly told it. Such guesses are too risky, when so many "un-" words fail to conform to this pattern: "unified", "uncle", "ungulate" and so on.)
Newly defined adjectives cannot be used when creating things, because they are not explicit enough. Inform could not satisfy:
because there is not enough information: by whom is the Ballroom occupied? How large, exactly? On the other hand, newly defined adjectives are very helpful in conditions and for rules, as we shall see later on.
It is occasionally clumsy having to refer to the subject of a definition using "it". We can avoid this and give the definition better legibility by supplying a name instead. For instance:
which is a good deal easier to read than
New conditions, new adjectives for giving more extensive definitions of new adjectives, using phrases.
In general, any noun can have adjectives applied to it, and this means that values can have adjectives just as objects can. We have already seen that they can (in some cases, at least) have either/or properties, and this gives them adjectives just as for objects. But we can also write out definitions which apply to values:
That makes the numbers 20 and 170 but not 37 meet the description "a round number", and the times 8 PM and 11:23 PM but not 9 AM meet the description "a late time". Because they come up fairly often, Inform contains several adjectives for numbers built in:
Similarly, two useful adjectives are built in to talk about text:
Adjectives can have multiple definitions and, as long as each applies to a different sort of noun, there will be no problem. We could write:
And these definitions of "round" and "odd" will not interfere with the ones applying to numbers, because Inform can always look at the noun to see which definition is meant in any given case. For instance,
must mean "round" in the sense of numbers, because the score is a number. Inform itself makes good use of this; "empty" also has meanings applying to rulebooks, lists and activities, for instance, as will be seen later.
Although it's more usual to give a definition to apply to a whole kind, we can actually give a specific definition to apply to just a single object or named value. For example:
The first definition of "subtle" takes precedence, of course, since it has the more specific domain – it applies only to red. The effect of this is that, if the player's female, the subtle colours are red and blue; if not, just blue.
Adjectives are often used in English to give a sense of where something is on a sliding scale. We talk about "a tall man" and "a short man", but without meaning that all men are either tall or short. If pushed, we might say that tall means about 6 feet and up, short means about 5 feet 6 and down, but we more often compare one person's height against another's.
Inform allows us to use adjectives in the same way. For example, every container has a number called its "carrying capacity". We can define:
These definitions are similar to those in the previous section, but have a very specific (and strictly enforced) shape to them. The adjective must be a single word. We have to say "its" (i.e., of it), not the ungrammatical "it's"; we have to specify a property, and a literal value of it, and we must either give an exact value or else conclude with "or more" or "or less". If we create something with one of these properties:
then they will have the most moderate values they can have, that is, the basket will have carrying capacity 10 and the thimble 5 (and of course the matchbox 7). Both of the following tests will then fail:
because the basket is neither huge nor small, but somewhere in between.
Sometimes the meaning of adjectives must depend on their context, as we see from the following example, where we assess heights in inches:
Inform then judges whether someone is or is not "tall" using different standards for men and for women, and
creates a man 72 inches tall and a woman 68 inches tall.
The special definitions in the previous section have a further effect. When we define:
we not only say how to test if something is large (see if its capacity is at least 10) and how to create something large (give it a capacity of exactly 10), we also create a new form of comparison. Thus,
are both true. If we also define "huge" and "small", as in the previous section, we also get comparisons "huger than" and "smaller than". Note that "huger than" has exactly the same meaning as "larger than": we can use whichever wording seems more natural. (For bacilli, for instance, we would probably not say "huger than", even though the meaning would be unambiguous.)
We can also compare two things to see if they share the same value of a property. For instance, to go back to the heights example, once we define "tall" and "short", we get that exactly one of the following will be true:
Though it will not always seem natural wording, we can use the comparison "the same P as" for any property P which has a value. Do we think "if the basket is the same carrying capacity as the thimble" is good English? Maybe, maybe not. But we are always at liberty to spell things out in full:
Lastly, if we define an adjective in this calibrating way, we also automatically benefit from the use of the superlative form. That is, if we define
then we can talk about things like this:
Though we should be careful, in the second case, because we might get nothing: maybe all the containers are closed at the moment this is used. And in general there might be several equally large largest containers, in which case we should not rely on getting any particular one of those rather than another.
Note that Inform constructs comparatives and superlatives by a pretty simplistic system. If we want to use these forms for an adjective expressing the relatively large size of a room, we had better go with "roomy" (roomier, roomiest) – not "spacious" (spaciouser, spaciousest).
A description can not only talk about things in terms of themselves, but also in terms of their relationships to the rest of the world. For instance,
are all valid descriptions. These are really abbreviations, having missed out the words "which is" or "who is", as appropriate:
and indeed those are also valid descriptions. The other sentence verbs can all be used here, too. So for instance:
And sometimes we should spell out "who is" regardless:
Since these clauses can be attached to the end of any valid description, descriptions can grow longer still:
Pedants who flinch when "which" is used to introduce a restrictive clause are welcome to use "that" instead.
"There" is a curious word in English, which mostly refers to some place which is being talked about – but which can sometimes mean the whole world. In Ian Fleming's novel "From Russia With Love", a chapter narrating a committee meeting of SMERSH officers in Istanbul ends with one of the Russians saying:
What does this "there" mean? It really just means that Bond exists. In fact, he's watching the meeting through a concealed periscope, but the SMERSH general doesn't know that. All he is saying is that Bond is out there somewhere, and is not imaginary, or dead.
Inform also allows "there is" (or "there are") to talk about what exists, or does not. This is especially useful if, for some reason, we don't want to give a name to something. For example:
Another reason might be that we want to create something but not put it anywhere. If Inform reads the sentence:
then it creates a man, gives him the name Bond, but places him initially off-stage – not in any room, that is, but available to be brought into play later on, like an actor who is not needed until Act II.
"There" also provides a useful way to test what exists:
Or even:
which will be true if the model world contains even a single woman, on-stage or off. The alternative "there are" can also be used:
but note that this does not necessarily imply more than one woman is present, despite the plural. If we want that, we have to be more explicit:
or, of course, we needn't use "there is" at all:
And we can also test non-existence:
What does "in" mean? It's worth just a brief diversion to cover this, because "in" has two subtly different meanings.
Meaning 1. Usually, if X is "in" Y then this is because of containment. A croquet ball is "in" a croquet box, which is "in" the Summerhouse. This is the standard meaning, and is the one which happens if we write something like:
or if we ask a question like:
This kind of "in" talks only about direct containment. If we ask
then the answer is that it isn't – it is in the box which is itself in the Summerhouse, but that's not the same thing.
This is almost always the meaning of "in" that we intend. This is only one of a number of relationships between objects – there are also "part of", "on", "worn by" and "carried by", for example. If we have
…then "if the bird feed is in the sundial" won't be true: the relationship here is one called support (being on top of, in effect), not containment. But there's no confusion because "on" and "in" are different words, so it's no problem that they have different meanings.
Meaning 2. Much less common. If X is "in" Y and Y is a region, then the meaning is slightly different. Suppose the Garden Area is a region, and contains several rooms – the Croquet Lawn, the Terrace and so on. Then
are all true. This seems very natural, but in fact is quite different from the first meaning of "in". It allows rooms (and even other regions) to be "in" a region, and it allows indirect containment.
How Inform decides. So which meaning does Inform use, and when? Since these two meanings are so different, it clearly matters.
The answer is that meaning 1 is always the meaning of "X is in Y" unless Y is explicitly the name of a region. Thus:
is meaning 2, because "Garden Area" is the name of a region. That seems fair enough, but values are indeed sometimes given names (becoming "variables", or values "that vary"). Suppose "mystery value" is a name for a value which is an object, but which has different identities at different times. Then Inform reads
as meaning 1, because whatever "mystery value" is, it isn't explicitly a region name, even if from time to time it might happen to be equal to a region.
That sometimes makes meaning 2 difficult to express. If we ever need it, and this is fairly rare, we can write it like so:
because "regionally in" is always meaning 2 of "in".
Like "in", "nothing" has two slightly different meanings, though here there's much less potential for confusion.
Meaning 1. "Nothing" as "no thing". This is the meaning in sentences like:
And similar for conditions like "if the box contains nothing". It's a word which describes the absence of things: it says that, though there might have been many possible items here, it turned out that there were none.
Meaning 2. "Nothing" as a value. This is much less commonly seen, but sometimes Inform stores a value such as a property (or a variable) which always has to be an object. In some circumstances, "nothing" is then a special value meaning that this is not set at present. For instance,
The "matching key" property of a container is always an object, but is allowed to be "nothing" when there isn't a matching key anywhere. (If such a container is locked, nobody will ever be able to unlock it.)
How Inform decides. So which meaning does Inform use, and when? The answer is that it depends on the relationship being talked about. When this is "is", values are being compared and we are using meaning 2. But when it is any other relationship, like "is in" – which talks about containment – then we are using meaning 1.
Two of the adjectives built into Inform are:
So we can write descriptions such as "someone visible" or "a touchable container". We also have adjectives "invisible" and "untouchable", as might be expected. The visibility adjectives are particularly useful because the following is likely to go wrong:
This tests whether the room is dark, of itself; Helen may in fact be able to see by means of a torch, but the room is still "dark".
We can also talk about what other people can see and touch:
are synonymous. Similarly for touch; and we can write such conditions as
Note that it is essential to establish who does the seeing and touching: so "something which can be seen" will not be allowed, whereas "something which can be seen by Helen" will.
In fact, inside Inform the adjective "invisible" (for instance) has the following straightforward definition:
The exact definitions of visibility and touchability are complicated, because there are so many ways in which vision and touch can be obstructed, but the gist is that they behave as one would expect. Note that in darkness, nothing is visible, and that nobody can see from one room to another. In general anything invisible is also untouchable, but there are a few exceptions to do with being in the dark. Lastly, the player's own body (usually called "yourself" during play) is both visible (in light) and touchable.
Another useful adjective built into Inform is "adjacent". Two rooms are said to be adjacent if there is a map connection between them which does not pass through some barrier such as a door. This is easily tested:
We usually want to know about the places adjacent to the current scene of the action, so that is what the adjective "adjacent" means when applied to rooms. For instance:
As with the case of "visible", the adjective is a cut-down version of the more general relationship. This often happens: "worn" and "carried", for instance, imply "by the player" unless something else is specified.
If we want to ask a more direct question, we can obtain specific map connections as follows. (Recall that every map connection leads either to a door, to a room, or to nothing.) If we know which direction we want to look in, then the easiest thing is to use its relation – every direction in the map, say "north", has its own relation, say "mapped north of". So:
Alternatively, and particularly if the direction is not a constant,
This phrase produces the room which the given map direction leads to, or the special value "nothing" if it leads nowhere. If it leads to a door, the result is the room through that door. Examples:
This phrase produces the door which the given map direction leads to, or the special value "nothing" if it leads nowhere or to a room. Examples:
This phrase produces the object which the given map direction leads to, which will always be either a room, a door or the special value "nothing". The phrase is used mainly by the Standard Rules, for technical reasons, and usually it's better to use "room … from …" or "door … from …" instead.
The map can be a great sprawling mass of rooms and doors connected together, and it can be quite hard to find a way through it one step at a time.
This phrase produces a direction to take in order to get from A to B by the shortest number of movements between rooms, or produces "nothing" if there is no way through at all. Example:
Best routes are ordinarily forbidden to go through doors, but if the suffix "using doors" is added as an option then any open or openable and unlocked door may be used on the way; and if "using even locked doors" is given, then any door at all will do. Since magnetism is no respecter of property, that seems right here:
In practice this simple approach sometimes produces impossible journeys, rather the way Google Maps directions from New York to London would recommend driving down to the docks and then swimming. A more careful approach is to use:
This phrase produces a direction to take in order to get from A to B by the shortest number of movements between rooms which match the given description, or produces "nothing" if there is no way through at all. Example:
The condition – in this case, that "visited rooms" must be used – also applies to both ends of the journey, so if either Drawbridge or Keep are unvisited then this is "nothing". (Similarly, saying something like "…through containers" would mean there is never a route.)
Lastly, the following phrases can find out how long the journey would be. (They are quite a bit faster than using the "best route…" phrases repeatedly and counting.)
This phrase produces the number of map connections which must be followed in order to get from A to B by the shortest number of movements between rooms. If A and B are the same, the answer is 0; if there is no route at all, the answer is -1. Example:
This phrase produces the number of map connections which must be followed in order to get from A to B by the shortest number of movements between rooms matching the given description. If A and B are the same, the answer is 0; if there is no route at all, or if either A or B fail to match the description themselves, the answer is -1.
Route-finding makes it possible to write quite sophisticated conditions concisely. But these sometimes run slowly, because they call for large amounts of computation. How rapidly Inform can find routes depends on which of two methods it uses. Both have advantages – one is fast but needs large amounts of memory, the other is slow but economical. We can choose between them with one of these two use options:
If neither is specified, "fast" is used where the project uses the Glulx virtual machine (see the Settings panel), and "slow" on the Z-machine, where memory is tighter. Fast route-finding is ideally suited to situations where dozens of characters are constantly route-finding through the map as they meander around in a landscape.
Indirect relations for route-finding through a relation rather than the map.
When testing conditions, we normally talk only about specific things, or else ask if a particular circumstance happens:
But we can also use "all", "each" or "every" to check the whole range:
Inform allows other English "determiners" (as they are sometimes called), as well:
are true if at least one case is true, if a majority (any number greater than one half) or at least 80 per cent of the possible cases are true, respectively.
And we can also use "none" and "no". These three are all ways to say the same thing:
though it may be clearer style to find a positive way of putting things:
All, each and every can be applied to values, too – but only in some cases. For example, suppose we write:
And suppose that, during play, we assign the "found" property to any colour which the player notices on a wall. We might then want to write conditions like so:
But we always have to bear in mind that Inform might have no reasonable way to decide these questions. It will refuse to allow these, for example:
(even supposing the adjective "palindromic" has been defined) – there are practically infinitely many possible numbers and texts, so the search cannot sensibly be done.
Lastly we can also ask for a more specific number of possibilities, like so:
Likewise for "less than", "at least", "all except". Something to watch out for is that
will be found true if there are (say) three open doors: after all, if three doors are open, then certainly two doors are. So this is not quite counting. We can be more precise by writing
The "all but" counts – say, "if all but two doors are open" – are exact: if, in fact, all of the doors are open then this will be found false.
We can often use these counting forms with values, too. As with the use of "all", this is allowed only if the kind of value is one which can reasonably be searched through. For example:
are allowed because the built-in kind of value "scene" (of which much more later on) has only a small number of possible values.
Lastly, note that the "the" in text like "two of the doors" matters: without it, the phrase will not be recognised as a requirement on the number. (This is to make sure that names of things like "two of hearts" are not misinterpreted.)
"Actions" are what we get if we try to break down a narrative into its irreducible parts. We might casually say that we are "going shopping", but this involves many smaller steps: going north, going east, entering the shop, examining a loaf of bread, taking it, giving money to the baker, and so on.
An action is an impulse to do something. This may or may not be a reasonable aspiration, and may or may not be achieved. The player's exploration of an interactive fiction is made by a sequence of actions, so much of the designing process comes down to responding to these actions.
We write actions using present participles. For instance, if the player types "take napkin" or "get the napkin" or something similar then the resulting action would be written as:
The details of what words the player actually typed are unimportant to us: we deal only in actions.
Every action ends in success or failure. In this context, success means only that the player's intention has been fulfilled. If the player sets out to take the napkin, but finds a million-pound banknote in its folds instead, the action will be deemed to be a failure.
The testing command ACTIONS causes Inform to log every action as it happens, and what its outcome is. (ACTIONS OFF turns this off again.) For instance:
A good way to get a sense of the constant flow of actions is to use this command and then wander around an existing work, trying things out. ACTIONS can also give an insight into the web of rules governing play: there are more than ten different ways an attempt to take something can fail, for instance.
An action is ordinarily handled by running it through Inform's extensive rulebooks of what might be called normal behaviour. An action such as "taking the napkin", for instance, will be run through numerous checks to see if it is physically reasonable, and then provided all is well, the napkin will be moved into the possession of the player.
Instead, though, we can bypass the rules to do with an action and do something else:
This is an example of a "rule": a set of circumstances followed by a list of instructions. When those circumstances apply, the instructions are carried out. In the case of an "instead" rule, after this is done the action is immediately ended (and counts as a failure, since the original intention has been thwarted).
A friendly alternative can be used when there is only a single instruction, as here: in such rules the colon can be replaced with a comma. Thus:
Despite what was said in the previous section, instead rules do not quite bypass all of the usual rules. Inform knows that certain actions require light: for instance,
and if it is dark then none of these actions will be allowed, and any instead rules about them will not even be reached. Similarly, Inform knows that most actions require physical access to their objects: so "taking the napkin" would be blocked if the napkin were, say, inside a closed glass bottle, whereas "examining the napkin" would not. So an instead rule can only take effect if the action has already passed these basic reasonability tests.
"Before" rules genuinely precede checking of any kind. They also differ from instead rules in that they do not automatically stop the action in its tracks. Rather, they are provided as an opportunity to ensure that something else is done first. For example:
whence
We have seen that instead rules automatically stop actions, whereas before rules automatically allow them to continue. We sometimes want to change this. The magic word "instead" can therefore be tacked on to any instruction in a before rule, and will have the effect of immediately stopping the action at that instruction. Thus the following two rules are (almost) equivalent:
It is also possible to be explicit about stopping the action:
This phrase stops the current rule, stops the rulebook being worked through, and finally stops the action being processed. Example:
Finally, we can prevent Inform from stopping the action when it otherwise might:
This phrase ends the current rule, but in a way which keeps its rulebook going, so that the action being processed will carry on rather than being stopped. Example:
An "instead" rule ordinarily stops the action when it finishes, so the "continue the action" is needed to make things carry on. (This rule would have been better written as a "before" rule, in fact, but it shows the idea.)
As a general principle, it is good style to use instead rules whenever blocking actions, and before rules only when it is genuinely necessary to do something first but then to continue: in fact, it is good style to use "stop the action" or "continue the action" as little as possible.
Chapter 2 noted that surveys of Inform source text showed that the three most popular phrases used by authors are "say", "if" and "now". The fourth most popular is "try", which allows us to trigger off actions ourselves, rather than waiting for the player to type something which generates them. Thus:
This phrase makes the action, which has to be named literally, take effect now. Example:
It's as if the player had typed GO UP as a command. Note that the action has to be specific:
is not allowed, since it doesn't say exactly what is to be eaten.
The word "try" is intended to make clear that there is no guarantee of success. For example:
could go wrong in any number of ways – perhaps the door is closed already, perhaps it is not openable, perhaps somebody has wedged it open. It would be safer to write:
There's no need to say anything if closing didn't work, because the closing action will have done that already. A neater approach still is to use:
This phrase makes the action, which has to be named literally, take effect now, under the "silent" convention which means that routine messages aren't printed. Example:
Silence is maintained only if this new action, the taking of the napkin, is successful (so if the napkin is successfully taken, the text "Taken." will not appear): if the action should fail, a suitable objection will be voiced as usual.
So now we have:
And this is neater because it won't produce a pointless "You close the front door." message.
Stored actions for how to store up actions as values and try those, too, so that isn't necessary to name the action as literally as in the examples above.
There is pleasantly little to be said about "after" rules. If an action has survived all the rules in its way, and has actually succeeded, then we need to give the player a response which acknowledges this. Inform's normal rules will be sufficient to say something undramatic: for instance, if "taking the napkin" has succeeded then it will reply "Taken." to the player.
An after rule is an opportunity to say something more interesting:
(Well, slightly more interesting.) After rules automatically end the action (as a success), which is what we would want in the above case. Allowing it to continue would simply result in "Taken." being printed as well. However, should we really need to do something and then carry on:
A few actions apply not to items alone, but also involve what might be called conversation. The first is the one used for looking things up in books (which is conversation of a kind, even if the author is not present): "consulting … about …". For example,
Note that what follows "about" here is a piece of text in double-quotes, and not the name of something. It can be almost any text at all, and in fact we shall later see (in the chapter on "Understanding") that we can match complicated patterns of words, too.
Similar actions are used for conversing with people:
These would be produced by commands like "ask sybil about verses", "tell sybil about persians" and "answer i am mad". Answering is little-used except that it also catches commands like "sybil, something unrecognized", which inexperienced players sometimes type. Asking and telling, however, are important actions and the difference between them is often worth preserving. If you would prefer to make "tell sybil about X" do the same as "ask sybil about X", the following rule would serve:
Games with a lot of conversation often involve great heaps of rules like the ones above, which can be repetitious to type out. We shall also later see (in the chapter on "Tables") that we can tabulate questions and answers in a much more concise way, if we prefer.
Topic columns for table-based ways to store and retrieve conversation.
The five senses are all simulated with actions. Sight is so informative that it is handled by a whole range of actions: "looking", which describes the general scene; "examining something", which takes a closer look at a specific thing; "looking under something", and so on.
The other senses have one action each: "listening to something", "touching something", "tasting something" and "smelling something". It makes no sense to touch or taste the general scene, but listening and smelling are a different matter: we often just listen, without listening to anything specific. If the player types the command "listen", Inform understands that as listening to the current location: similarly for the bare command "smell". Thus:
A description can include more than one choice of action. For instance:
matches either of "examining the desk" or "searching the desk". We can have more than two actions, of course:
The actions combined like this need to be compatible with each other, at least a little. For instance, this will generate a problem message:
because it makes no sense to "wait the desk". On the other hand, this is fine:
The general rule is that if we specify one or more objects ("the desk" in the above example), then each of the actions we quote must take at least that many objects.
For example, the following saves us writing the same basic rule three times over:
The special description "doing something" (or "doing anything") matches any action, and "doing something to …" also allows the noun to be specified.
For instance, the following puts its object out of bounds:
We sometimes need to be a little careful here: "waiting" qualifies as "doing something", but not as "doing something to something", because there is no object. "Putting the handbag on the cucumber sandwich" would also not qualify as "doing something to the cucumber sandwich" – only to the handbag.
More often, we would like to restrict the range of allowable actions to a select few. For instance:
(Or we can write "except" instead of "other than".) Or we might have an object, too:
Note the "with", which is crucial here. Without it, the rule is subtly different:
This second version matches if the action is, say, taking a shield, or even just looking, because that would be an action other than examining the dagger, taking the dagger or dropping the dagger.
Once we begin applying rules to actions which are not entirely known in advance, we have a problem: there's no way to find out what specifically is happening. Consider the following:
This is fine as far as it goes, but clumsy. What if the player had examined a human being? Then "it" would be inappropriate. A better approach would be this:
The "noun" and, when necessary, the "second noun" are values which can be used in any rule about actions, and it follows that they can also be substituted into text, as this example demonstrates. Results might include:
This seems a good moment to mention that if you use "The" in a substitution, then a capitalised "The" will be used so long as this is grammatically correct (Lady Bracknell, as a proper noun, takes no article); "the" becomes a lower-case "the" along the same lines; and "a" a lower-case indefinite article.
Three elaborations of action descriptions increase the range of possibilities further.
Like the objects to which the action applies, this location – the "in" clause – can take any description, not just an explicit place like "Supernatural Void":
But we often want a rule to apply in any of a set of rooms: and where, unlike the "dead end" example above, the rooms have nothing much in common except where they happen to lie on a map. For instance, we might want a rule to apply only inside a given building, or a garden consisting of five miscellaneous rooms. If so, we can create a "region" as a convenient way to refer to that group of rooms:
Relative location can also be important: relative to other people, that is -
As might be guessed, this applies when the action takes place in the same location as the person named: and of course that person can also be described more vaguely ("… in the presence of a woman", say), and can just as easily be an inanimate thing ("… in the presence of the radio set").
Lady Bracknell is a pushover compared to some matriarchs:
The last of the optional clauses we can tack on to the description of an action is the most general of all. We can add "when" and then any condition at all, as in:
This supposes that the radio is so loud that it can be heard from any room: we could muffle it so that it's only audible from the room it is in like so:
Going is an action defined like any other: it is the one which happens when the player tries to go from one location to another. But it is unlike other actions because it happens in two locations, not just one, and has other complications such as vehicles and doors to contend with. To make it easier to write legible and flexible rules, "going" is allowed to be described in a number of special ways not open to other actions, as demonstrated by the following example story:
Note that "going nowhere" means trying a map connection which is blank, and if no rules intervene then "You can't go that way" is normally printed. Unless "nowhere" is specified, descriptions of going apply only when there is a map connection. So "going from the Musicology Section" would not match if the player were trying to go east from there, since there is no map connection to the east. Similarly, "going somewhere" excludes blank connections.
The places gone "from" or "to" can be specific named regions instead of rooms. This is convenient when there are several different ways into or out of an area of map but a common rule needs to apply to all: so, for example,
Note that it must be "going nowhere from the Wilderness", not "…in the Wilderness". (Note also the caveat that the regions must be named: "going from a region", or something similarly nonspecific, will not work.)
An important point about "going… from" is that, as mentioned in general terms above, it requires that there is actually a map connection that way: whereas "going… in" does not. Suppose there is no map connection north from the Wilderness. Then:
The first of these never happens, because it is logically impossible to go north from the Wilderness: but the second does happen. (Technically, this is because "going north" is the action, and "in the Wilderness" a separate condition tacked onto the rule.) This distinction is often useful – it allows us to write rules which apply only to feasible movements.
This may be a good place to mention a small restriction on the ways we can specify an action for a rule to apply to, and how it can be overcome. The restriction is that the action should only involve constant quantities, so that the following does not work:
because "the location of the rabbit" is a quantity which changes in play (the player can pick up the rabbit and take him to the Dome, for instance). However, we can get around this restriction by defining a suitable adjective, like so:
Adding to the previous example story, we apply rules which depend on travelling by a particular vehicle:
And, lastly, rules which apply to movements through particular doors:
(Note that these apply whether the action is "going east" or "entering the green baize door", each having the same effect.) The last rule is worth a second look: the normal way that a "going" action is reported is to produce the room description of the new location. So if an "after" rule stops the action before we get to reporting, we have to produce any room description by hand (hence the "try looking" to cause the looking action). Alternatively, we could simply say something and let the normal course of events take place:
Finally, going is an action which can also happen while the player is pushing something from one room to another, and we can describe this like so:
"Going" is not the only action which moves the player. Another is "exiting", an action which moves the player out of whatever he/she is currently in or on. This action is often caused by the player typing just OUT or GET DOWN, and there's no noun as such. But Inform allows the syntax "exiting from" to make it easier to write rules about the exiting of particular containers or supporters:
Especially when people need to react to events going on around them, it is helpful to be able to categorise actions into whole areas of behaviour. For instance:
Here a new kind of action called "unmaidenly behaviour" has been created and then used in the description of an instead rule. The convenience of this approach is that when further actions suddenly occur to us as also being unmaidenly – say, attacking Mr Carr – we only need to add a single line:
And this will automatically be reflected in any rules which concern the consequences of failing to be ladylike.
(Note that we were only allowed to say that "Kissing Mr Carr is unmaidenly behaviour." because Inform already knew from earlier sentences – see the example below – that Mr Carr was a person, and therefore that "kissing Mr Carr" made sense as a description of an action.)
We come at last to the final thing which can be specified about an action, and appropriately enough it must be specified with the final words of the description. This is the way to talk about repeated activity:
Note that we are allowed to spell out numbers up to twelve in English words, but beyond that must use digits (thus "twelfth" is allowed but not "thirteenth": "13th" should be used instead). The following example is instructive:
This means that it is the fourth time a "taking…" action has been tried, and does not mean that the same item was taken each time. Also, note that we are counting the number of times the action has been tried, not the number of times it succeeded.
We can also reckon the number of consecutive turns on which an action has been repeated, by talking about "turns" instead of "times", as demonstrated in the following example story. Note also that we are allowed to use the phrase "doing it" to mean "the same description as the previous one except for the part about turns or times", like so:
Note once again that numbers above twelve must not be written out, so "more than twelve times" would be acceptable, but we would write "more than 13 times".
In this chapter, all actions have been carried out by the player, all have been drawn from the standard stock of built-in actions ("unlocking", "taking", "going" and so forth), and all of those built-in actions have been allowed to work in the standard way – we have seen how to prevent the taking of something, and how to give this unexpected consequences, but not how to make taking work in an entirely different way.
All three of those restrictions will later be lifted in the chapter on "Advanced Actions", but otherwise we have covered the ground thoroughly, and it is time to move on to the techniques enabling us to do more than make tart replies to the player: it is time to change the world.
So far, what we have done in response to the player's commands amounts to little more than a few ripostes. The simulated world does change during play, as the player moves from room to room or picks up things, but all of this is happening automatically, not at our direct instruction. How then can we make the world change?
Recall that the world consists of rooms, in which are things, and that all of these have properties appropriate to their kinds. Some properties are either/or ("open" or "closed" but not both and not neither), while others have values (the "matching key" of a lockable door, for instance). Finally, we may also have created some free-standing values or "variables".
We take the last example first, as it is the simplest. Suppose we have:
The new phrase here is "now". This automatically checks that the new value is one which makes sense in the given context, so for instance it would not allow either of these:
the former being a number, and the latter a room, so that neither is a direction. Similarly, "now" will not allow constant values to be changed. So
…will result in a problem message; it's like writing "now 1 is 2". The difference between "the prevailing wind" and "blue" is that the wind was declared to be a "direction that varies", whereas blue wasn't.
The command prompt is the text printed by Inform to ask the player for another command. Ordinarily this is simply a greater-than-sign, ">", so we tend not to notice it as text at all. Internally, though, it is a variable value called "command prompt", which means we can change it.
For example, this will be a more conversational sort of prompt:
Whereas this will be more up-to-the-minute and demanding:
("Time of day" is another variable value, which is fairly self-explanatory, but will be covered in detail later on.) The prompt can be changed at any point, so can be used to indicate the current situation, or even as a sly way to introduce a sort of conversation between computer and player.
The status line is the black bar along the top of a story being played, which ordinarily displays the current position; in a story with scoring, it also usually shows the score and number of moves taken. Like the command prompt, it is not fixed but results from values which can be changed: the "left hand status line" and "right hand status line".
The default values are "[the player's surroundings]" for the left hand status line and "[score]/[turn count]" for the right hand status line (if there's scoring; it's blank otherwise). Score and turn count are numbers which vary in play (more about scoring later); "[the player's surroundings]" is a text substitution really intended for just this purpose:
This text substitution produces a succinct description of where the player is, be this in darkness, in a lighted room or inside an opaque container such as a large packing case. Example:
These make useful elements to juggle in redesigning the status line, as in the following example:
The text in the right hand status line should be kept no more than 14 letters long, including any spaces. The left hand status line has more leeway, but should still be kept brief.
Awarding points for scoring.
When we have an either/or property, we can set it like so:
If it is open already, nothing changes: in any case nothing is said to the player unless we give explicit instructions to that effect, as we've done here.
Inform protects its model world from accidental damage in several ways, one of which is to ensure that things are not given properties which they are not allowed to have. So this, for instance, will not be accepted:
More subtle problems arise if it is not possible to tell, when the story is being constructed, what the object in question will be: for instance, if we try to change a randomly chosen object to be "unvisited". Inform therefore makes additional checks during play, printing up a suitable message only if the rules are violated. The net effect is that it is impossible for the oaken door ever to have the "unvisited" property.
Changing properties with values is very similar:
Inform checks three different things to ensure that this change is safe to perform. Firstly, the value must be the right kind for the property in question, so this for instance would be rejected:
Secondly, the object in question has to be allowed to have the given property. This, for instance, would be disallowed:
(since "initial appearance" is a property which only things can have, not rooms). Finally, the object has to actually have the property, not just have the right to have that property. Thus:
…is only permitted if the Closet is designed with a "printed name". In fact this is certain to be true: all rooms and things automatically have a printed name, which is the short boldface description in the case of rooms, and the usual text briefly describing something in the case of things.
"Now" is a simple way to change many things in Inform, but it's cumbersome to change the map of the model world using "now", because the map is such a complicated arrangement. (It's not a property: it's a sort of mesh of relations.) So a special phrase exists to change map connections:
This phrase alters the map so that the given map connection is made. Note that connections can be made to rooms, but not doors: the positions of doors are fixed. Example:
Since "nothing" is not a room, this doesn't allow us to change the exit to nothing, so there is a separate definition of:
This phrase alters the map so that the given map connection is unmade. Example:
Altering the map itself is not a very subtle way to adjust when and where the player can move – writing suitable rules is usually a cleaner solution – so this phrase is best avoided unless really needed.
This seems a useful point to clarify something already seen. We normally call a property with a value something like:
We are sometimes allowed to omit the "of the …" part, and simply call it "the printed name", for the sake of brevity. For instance, the following room description:
will result in "West Ballroom" being substituted for "[printed name]". Since the text belongs to the West Ballroom, that is assumed to be the owner of any properties named in its description. Similarly:
Here the owner of the "printed name" is assumed to be the noun referred to in the action – in other words, the "something" alluded to in the rule.
We have now seen how to change the properties of rooms and things, and also any freestanding values which may have a bearing on the model world. We are not allowed to change the kind of anything during play. Our remaining freedom is to move things around. It would make no sense to move rooms around, because rooms are the fixed reference points in our geography, but anything else is mobile. This even includes things which are supposedly "fixed in place", for unlike the player, we have god-like powers. (There are minor restrictions: backdrops are trickier to move, since they are present in several rooms at once – see the next section. And doors, at the junction between two rooms, cannot be moved.)
Here is how to move something:
This phrase moves the first-named object to the second. Example:
The first object named has to be a thing; the destination must be a room, as here, a container, a supporter, or a person. When something is moved, all its parts and contents (and all their contents, and so on) move with it. If the thing being moved is a person, then the destination is required to be a room or an enterable container. (In particular, a person cannot be carried by another person.)
Two options can be used if the object being moved is the player.
omits the description which would otherwise be produced. A compromise is to use:
which gives a full description if the player has never been here before, but only a brief one if it is a familiar scene. These options have no effect for any other objects being moved.
If the destination is a person, like so:
then it will be carried rather than worn. We could arrange for it to be worn instead by writing
"Now…" is a much more flexible phrase than "move": more on this shortly.
A backdrop can be in several rooms at once. When created, its position can be given as any specific collection of rooms, or as a region, or even as "everywhere". For instance:
Moving backdrops is not like moving other things, because there's no single destination. There are several possibilities:
(a) A backdrop can be moved to a region. If we define:
then we can write either of
and either way, the stream is now found in the Rock Pool and the Ledge but nowhere else.
(b) A backdrop can be moved to a category of rooms:
This phrase moves the backdrop so that it is now present in every room matching the given description. Example: If we define
then we can write
This phrasing, "move the … backdrop to all …" is deliberately meant to look unlike the simpler "move … to …", to emphasise that this kind of movement is possible only for backdrops.
What then happens is that the stream is present in whichever rooms are currently wet. But the stream's position is ordinarily checked only after movements, for efficiency's sake. So if the player is in a room which suddenly changes from being dry to being wet, the stream will not magically appear (though it will be there if the player goes out and comes in again). If this is not good enough, the phrase "update backdrop positions" can be used to ensure the accuracy of all backdrop locations after a dramatic change:
This phrase runs through all backdrops in the model world and makes sure they are correctly in, or not in, the current location, so that everything appears right from the player's point of view. Example:
(c) A backdrop can be moved to be either everywhere or nowhere:
The player is a thing, too, and can also be moved, which has the effect of instantaneous transportation, without the need for a suitable map connection to the new location. For instance, these are equivalent:
This will ordinarily result in a room description of the Bodleian Library being printed up, but that might not always be desirable. For instance:
Thus tacking on the option "without printing a room description", remembering to add the comma, omits the description which would otherwise be produced. A compromise is to use the option "printing an abbreviated room description": this gives a full description if the player has never been here before, but only a brief one if it is a familiar scene.
The player's point of view can also be moved by shifting to another character. Suppose the story features two people, Alice and Bob, and the player at the keyboard is giving commands to Alice, and seeing everything from her point of view. The phrase:
switches the perspective so that now Bob is the one controlled by the human player, and it's Bob's point of view which counts. The human being at the keyboard may feel a sense of having jumped abruptly from place to place, but in fact neither Alice nor Bob has moved.
A change of player can sometimes cause confusing things to happen, if it takes place as part of a successful action. Suppose there's an action called "possessing", which enables the player to possess somebody else's body; and suppose the player types POSSESS ADELE. The action succeeds, so that the player moves into the mind of Adele. But that means that at the end of the action, the player is no longer the actor – that is, no longer the person who began the action; and consequently, Inform won't use the report rulebook to say what has just happened. It's a strange business, moving into another body.
Some things will occasionally be in a limbo state called being "off-stage": like actors or props not needed in Act II, but perhaps to be brought back on-stage later, they wait on the sidelines. Anything created with no apparent location will start the story off-stage, as in the case of the lamp here:
(Such things are easy to see in the World index because they are listed after all of the rooms and their contents, not belonging inside any room.) If we wanted to make this clearer to a human reader, we could add:
to emphasise the point. In this context, "nowhere" means "in no room". Moving the lamp onto the stage-set, so to speak, is easy:
or perhaps:
and we can whisk it away again like so:
(We can't say "now the lamp is somewhere" because that's too vague about exactly where it is.) In older builds of Inform, the usual thing was to write "remove the lamp from play", but that's now a deprecated phrase: better to use "nowhere" instead.
Removes the given object from play, so that it is not present in any room. We are not permitted to remove rooms, or doors, or the player, from play; but we are permitted to remove backdrops, making them disappear from all rooms in which they are present. Example:
We can test whether something is on-stage or off-stage with:
Inform also understands two adjectives for this:
Because these are adjectives, they can be used in a few ways which "nowhere" and "somewhere" can't, such as:
Note that "on-stage" and "off-stage" apply only to things. Rooms, directions and regions are the stage itself: so it makes no sense to ask the question of whether they are "on-" or "off-". Doors are always on-stage; a backdrop, say "the sky", is always on-stage unless it has been taken off by writing something like "now the sky is nowhere".
"Now" has already appeared several times in this chapter, being used like a Swiss army knife to change values of all kinds:
In fact, "now" is by far the most flexible phrase known to Inform.
This phrase makes the condition become true. Examples:
Inform issues a problem message if the condition asks to do the impossible ("now 3 is an even number") or is vague ("now the duck is not in the Lily Pond") or not in the present tense ("now the front door had been open").
We've now seen all three things which can be done with a condition S which describes the world:
For instance,
Once we begin to deal with named values (or table entries, list entries or other ways to describe places where values are kept), we find that we often want to change them. We could if we wanted always use "now" for this, but it can be a little clumsily worded if we want to increase or decrease something:
Because of that, we have some convenient abbreviations which have the advantage that the value being changed only has to be named once:
This phrase increases the variable, table entry, list entry, or property by the given amount, which must be of a compatible kind. Example:
This phrase decreases the variable, table entry, list entry, or property by the given amount, which must be of a compatible kind. Example:
An even greater abbreviation can be made when we are changing a number by 1 either way:
This phrase increases the variable, table entry, list entry, or property by 1. Example:
This phrase decreases the variable, table entry, list entry, or property by 1. Example:
"Increment" and "decrement" are traditional computing terms, though they have been used in engineering for at least a century and in finance for longer still.
We have seen that while rooms are fixed, their contents move around, so we will need ways to examine the current whereabouts of things. The following examples show the kind of conditions allowed:
These are exactly like the assertions which we use to set up the world, except that we make them questions by placing "if" in front. But we shall later see that we can also use three other tenses, not to mention plural forms, so that new verbal forms like "had not been inside" and "were not supported by" are legal here (which they would not be in assertions). What we are not allowed is to contract these verbs with apostrophes: "isn't", "hasn't" and "hadn't" are forbidden.
Overwhelmingly the condition we check most is whether the player is carrying something. The following are therefore equivalent:
And similarly for "not carried", "worn" and "not worn". To be precise, if a form of to be carried or to be worn is not followed by any other description, then "the player" is assumed to be doing the carrying or wearing.
The examples just given were all basically of the form "X relation Y" where X and Y were specific names of things. For example,
Just as actions could be described with patterns to be matched ("taking an open container", say), so can the positions of things. Giving subtler descriptions of our X and Y sometimes broadens the possibilities, sometimes narrows them:
In the first case, Y is allowed to be one of a whole range of things – any of the women existing in the world. This makes for a broader condition. In the second case, Y has not only to be the cupboard, but at a time when it is closed: which makes for a narrower condition. We can, of course, also vary X:
And we can even vary both X and Y at once:
a condition which will be true if, anywhere in the story's world, any woman is holding any animal.
Conditions like "if somebody is in an adjacent room" allow complicated tests to be performed with a minimum of fuss, but it's rare that we want to know only whether they are true: more likely we also want to know which person, and which room.
For this purpose, we are allowed to supply a name for any such vaguely-described object which comes up, and then to use that name thereafter.
We can even name more than one of the things discovered:
Note the brackets, which are essential. The result of typing "wait" is then
Of course, that might be just one of many animals held by women in the story. We shall later see ways to go through all of the possibilities found, performing some action with each in turn.
A calling, if we can use that word, should be made immediately after the noun it refers to, and not left to hang back after any relative clauses. For instance,
is allowed, but not
because there is too much potential ambiguity – are we trying to call the player something?
Repeat running through for systematically working on everything matching a description.
It is very often useful to know how many things are in a given situation, and for this purpose we have the "number of …" construction. For instance:
Whereas "a woman is holding an animal" makes the same test as "an animal is held by a woman", getting the same result, counting is not so even-handed:
are different questions and, unless the ration is strictly one lapdog per baroness, will have different answers. If Cruella de Vil has 101 dalmatians, they may be very different indeed.
It can also be helpful to count things with no particular location, like so:
For instance:
Provided that the possible range is finite, we can also use "number of" to count values which match a description. For instance:
or if we were to define
then "the number of colours" would evaluate to 7. As with other ways of talking about whole ranges of values, this only works if the range is manageable. "The number of numbers" cannot sensibly be worked out: there are infinitely many, for all practical purposes, and similarly for "the number of texts".
The descriptions outlined in the last few sections are intended to deal with almost all of the routine questions we might have about what currently resides where. It should be a last resort to use the following more primitive way to inspect the world.
This phrase produces the container, supporter, carrier, wearer or room in which the object resides.
It's sometimes useful to go the other way. When something has possessions, we can find them out one at a time by running through a list.
This phrase produces the first of the list of things held by the object. Example:
This phrase produces the next item of the list of things held by something. Example: suppose Baroness Orczy is carrying a lapdog and a string of pearls.
is then the string of pearls.
Sometimes we want to introduce random behaviour into play. We usually do this by generating random values, and then acting differently depending on what they are. The following:
produces, as it suggests, a random number drawn from the choices 2, 3, 4 or 5, each of which is equally likely to come up. In fact, this isn't limited to numbers:
This phrase produces a uniformly random value in the range given. Examples:
If we make a new kind of value:
then we can also take random values from it:
which has three possible outcomes, all equally likely.
We can also use random conditions:
This condition is true X/Yths of the time, where X and Y are the numbers. Example:
Here is a rule which applies only 15% of the time:
Testing IF which makes random choices can be rather frustrating, because a problem showing up on one attempt may not show up on another. We can get around this by making use of the fact that computers do not actually generate true randomness, but instead make a sequence of apparently random numbers by applying a complicated formula to each one in order to make the next. The starting point is a number called the "seed", because the next choice grows out of it.
This phrase changes the seed number as specified. Any random numbers generated after that depend only on the seed. Example: the following sentence will "fix" the process of generating these random numbers so that they are not random at all – the same sequence of random numbers will be produced on each run.
The seed value "1234" can be anything positive; a different sequence of random numbers will be produced for each different seed value. A seed value of 0 restores the RNG to properly random behaviour again.
Alternatively, it's possible the "fix" the RNG by clicking the "Make random outcomes predictable when testing" option on the Settings panel. This makes the behaviour predictable whenever the story is played within Inform, but (unlike the rule above) has no effect on the story file once released.
Writing "a random number" is not allowed, because the possible range is too large, but that was the only reason why not.
This phrase makes a uniformly random choice from values satisfying the description given. Example:
A problem message is issued if the range is too large (for instance, "a random text"). Unexpected results may follow if no value fits the description, unless we are describing objects, in which case the result is the special value "nothing".
For instance:
But it's important to worry about the possibility that nothing qualifies – here, that no adjacent rooms exist. The above would then say:
With the material from previous chapters, we are now able to set up a simulated world, to respond to the player's actions within it, and to make it change in perhaps unexpected ways.
The resulting experience can be as lively as we want to make it, but so far we have no very good ways to give it any structure: a beginning and an end, for instance, or a sense of plot. This next chapter is all about the passage of time, and it begins at the beginning.
We have already seen an example of how to write a rule which applies just once, at the start of the story:
The "when play begins" rules are checked only at the start of a story, not when a saved session is restored from disc. What happens is that these rules are followed, then the story's banner is printed, then the initial room description is printed up, and then the player is asked for a first command.
Traditionally-written stories award points throughout play, as an indication of progress. If we want to be traditional, we must first write:
Without this, the SCORE, NOTIFY ON and NOTIFY OFF commands do not work; the final score is not shown at the end of a story; and the status line above the player's text area shows only the turn count, not (as is more usual) both the score and the turn count. Changing the "score" (see below) has no visible effect, though it is not actually illegal.
With "Use scoring" in place, we can award points as follows:
substituting whatever number we feel is appropriate. We should be careful not to give out the same points over and over, that is, not to reward the same basic achievement many times over if the player simply repeats the same action. This, for instance, is open to abuse:
The player may simply take the trophy, drop it again, take it again, … and win five points every time around. We can prevent this by phrasing the rule more carefully:
("Was handled", not "is handled", because this rule happens after the trophy has been taken – so by the time this rule has been considered, the trophy is always handled.) Rather than being an open-ended scoring system, IF normally has a maximum possible score, which can be specified with a sentence like so:
The score and maximum score are just numbers that vary, so we can freely change them:
Another tradition of interactive fiction is that the player has a current 'rank' according to how far his or her score has got. We can (but need not) choose to provide such rankings, and should do so by specifying a table like this:
| Score | Rank |
| 0 | "Beginner" |
| 25 | "Amateur Adventurer" |
| 50 | "Novice Adventurer" |
| 100 | "Junior Adventurer" |
| 200 | "Adventurer" |
| 300 | "Master" |
| 330 | "Wizard" |
| 350 | "Master Adventurer" |
Typographically, tables in Inform look as much as possible like those found in non-fiction books: they can have many columns, so this is only a simple example (drawn from the actual rankings used by Infocom's Zork I, 1979). Each line in the source represents one row in the table, and the entries on a line must be separated by at least one tab character. (An entry might of course have several words with spaces in between, so a space is not enough to separate entries: this is the only context when Inform distinguishes between spaces and tabs.) The table must occupy a single whole paragraph, with no skipped lines or missing entries. We are free to use extra tabs to indent it if we like.
Ordinarily we must explicitly ask to use the information presented in a table, but the table of rankings is a special case: Inform uses it automatically, if it is provided at all. To be recognised it must have the name "Rankings" and must have two columns named and arranged as shown. The scores should be given in ascending order. Customarily, the score in the final row should be the maximum possible achieved in the story – so that only a player with maximum possible score can be awarded the final ranking – and the value of "maximum score" is automatically set to this bottom-row value if it has not been explicitly set anywhere else in the source text.
Short of something like a power cut, the story can only end when one of the two participants chooses to end it: either the player, by deciding that enough is enough, or us.
In story-telling, there are many kinds of ending: happy, sad, decisive, bittersweet, surprise. Inform doesn't try to interfere in that kind of artistic choice, but it does need to know one thing about the ending: is it final, or not? Many authors like to make additional menu items available if the player has completed the story right through, but not if she has reached an early or wrong ending. (See the activity "amusing a victorious player", for example.)
This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message "The End." The end is not considered final.
This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message "The End." The end is considered final, and any hidden menu options will be revealed.
This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message given in the text. The end is not considered final. Example:
This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message given in the text. The end is considered final, and any hidden menu options will be revealed. Example:
The closing message is traditionally set out in asterisks:
This style is traditional in IF, and goes back to 1980 if not earlier.
We can test the current state like so:
This condition is true if an end has been declared using one of the "end the story…" phrases.
This condition is true if no end has been declared using one of the "end the story…" phrases.
This condition is true if an end has been declared using one of the "end the story finally…" phrases, so that an ending has been reached which the author feels is a completion of the player's experience.
This condition is true if an end has been declared using one of the "end the story…" phrases, but not "finally", so the author feels that the player can get further experience by playing again and trying different approaches.
The rulebook "when play ends" is the matching bookend to "when play begins". It is followed when the story decides to end (not when the player simply gives up and quits), and before any epitaph like
appears. For example:
Surprisingly, the end is not always the end:
This phrase causes an ended story to resume exactly as if no "end the story…" phrase had been used. Example:
The phrase is likely to be sensible only as part of a "when play ends" rule. Other traditional uses include giving the player three lives, as in an old-school arcade machine.
The passage of time in interactive fiction is broken up into a succession of turns, in each of which the player types a request and is given a response. Usually each such request triggers one action, but sometimes a whole sequence are fired off, as when the player types "get all" in a cluttered room.
As we've seen, the variable "turn count" holds the number of turns of play so far. By convention turn number 0 is the time when Inform prints up the banner and any initial text; it becomes turn number 1 when the player's first command is typed.
One of the last things to happen in each turn is that Inform will apply any rules which have been set to occur "every turn", like so:
This is equivalent to writing:
Note that the text about blossom, which will quickly become tiresome, is said at the end of every turn, not at the beginning, and in particular not before the player's first opportunity to type a command.
As usual when defining rules, we can add stipulations: any condition can be attached using "when".
Inform keeps track of the time of day automatically: play ordinarily begins at 9 AM and each turn takes one minute. In some works of interactive fiction, time of day is crucial: in others, it is irrelevant or even, by a sort of tacit convention, non-existent. So Inform does nothing to act upon the time, or to reveal it to the player, without instruction. Nevertheless it is there.
A sentence like the following allows the initial time to be set up as something other than 9 AM:
Here, "3:13 PM" is a constant value of a kind not seen before: it's a kind of value called "time", and the value "time of day" is a time that varies. After one turn it will be 3:14 PM, then 3:15 PM and so on.
Note that the sentence above is an assertion (a statement about the initial state of affairs), not an instruction which can be part of a rule. It would be equivalent to write:
We more often change "time of day" to take care of drastic events:
Now that we have the time of day, we can of course use this value in room descriptions and the like:
It seems odd, though, to read a precise numerical description of the time here: after all, it isn't a digital clock. A friendlier version would use:
This text substitution produces the given time written out in English sentence form. For example:
might produce
To reiterate an example which came up earlier, we could even work the time of day into the command prompt, which would lend the proper sense of urgency to a story played out against the clock:
Clocks and watches vary considerably in how much detail they show, and we tend not to report the time over-precisely: half-past ten is an elastic concept. The following room description for the Clock Chamber comes across much more naturally:
The phrase "… to the nearest …" rounds off the given time, just as it sounds; as we'll see later, it can actually round off any arithmetic values, not just times. For instance, "9:58 PM to the nearest ten minutes" is 10:00 PM.
In talking about lengths of time, rather than times of day, it's useful to have these:
This phrase converts numbers into lengths of time. Example:
Because it's a phrase, not just a notation for writing constants down, the number doesn't have to be given literally:
Note that lengths of time can't exceed 1440 minutes.
This phrase converts numbers into lengths of time. Example:
Note that lengths of time can't exceed 24 hours.
Carrying out easy calculations with times is straightforward:
Here we are using two phrases:
This phrase produces a time earlier by the amount given, keeping within the 24 hour clock. Example:
produces 10:30 PM.
This phrase produces a time later by the amount given, keeping within the 24 hour clock. Example:
produces 8 PM.
Similarly, we have conditions:
This condition is true if the first time occurs earlier in the day than the second. In recognition of the fact that very few stories begin before 4 AM, whereas many run on past midnight, the start of the day is taken to be 4 AM: thus 3:59 AM is after 11:10 PM, but 4:04 AM is before it.
This condition is true if the first time occurs later in the day than the second. In recognition of the fact that very few stories begin before 4 AM, whereas many run on past midnight, the start of the day is taken to be 4 AM: thus 3:59 AM is after 11:10 PM, but 4:04 AM is before it.
We will occasionally need to perform more complex calculations with time, and in order to do that, we have a way to convert the time of day to numbers. Thus the phrase "the minutes part of …" takes a time and produces a number from 0 to 59; similarly "the hours part of …" extracts a number from 0 to 23, using the twenty-four hour clock.
This phrase converts a time to a number, then takes the result mod 60, which in effect produces the number of minutes after the hours are thrown away. Example:
produces 41.
This phrase converts a time to a number, then divides the result by 60, which in effect produces the number of hours after minutes are thrown away. Example:
produces 8.
To go the other way, we can convert any number to a duration by writing "minutes" or "hours" after it. For instance:
Note that "clock error" is a number, but "clock error minutes" is a time.
We often want to arrange for something to happen at some point in the future. Here is yet another timepiece:
The event here is called "the egg-timer clucks". It only happens if we instruct so, using one of the following phrases:
This phrase causes the given rule to be run at a given time offset from the current time of day. Example:
This phrase causes the given rule to be run at a given number of turns after the current one. Example:
This phrase causes the given rule to be run at a given time of day. Example:
If we know in advance what time we want something to happen, we can more simply write:
(Note that in either case such rules begin with the word "at": they are the only rules allowed to begin with the word "at".)
A small warning: timed events like these only have a chance to occur during the turn sequence, that is, once every turn. In most stories, one turn takes one minute, so there will in due course be a turn happening at exactly (say) 11:35 AM. But if the clock is being advanced faster than this, it's possible that there are turns at (say) 11:32 AM and then not until 11:37 AM. But an event set for 11:35 AM will nevertheless happen -- it will run at the first available turn after that time, which will be 11:37 AM. Events can thus happen up to half an hour late, though Inform cancels them if the elapsed time is greater than that.
The Scenes panel of the Index can be a useful way to see what events have been set.
There are two ways that descriptions of actions can be used as conditions. First, we can simply describe an action, and then the condition will be true if that is what the player is trying to do, and not otherwise:
This is actually an abbreviation for the longer, some would say preferable form:
Secondly, we can talk about the past as well as the present, which is very useful since interactive fiction often contains situations which are changed by earlier events.
More on the past tense later follows in the next section: note that "we are taking" has become "we have taken". For the rule to apply, it is not enough that the action "taking the lantern" has been tried: it must have succeeded. Note also that it's enough for any actor in the story to have successfully taken the lantern: it doesn't have to be the player.
The remaining sections of this chapter go into more technical ways to think about the progress of the story through time, and can be skipped at a first reading.
Conditions are clauses which require Inform to make a decision: is such-and-such true, or not true? We have already seen conditions attached to rules using "when":
and, as we shall later see, we will often want to write instructions like:
The condition is "the Sorting Hat is in the Hall", and during play this will sometimes be true and sometimes false.
A condition in the form "X is Y" is of course written in the present tense, and refers to the current state of affairs. Three other tenses are allowed. First, the present perfect:
is true if it has ever been the case that "X is Y" at the start of any turn (or any action). So, for instance,
will be valid if and only if the gate has ever been made open by any action (even if it is closed now), or if it started out by being open when play began.
Next is the past tense:
holds if and only if "X is Y" was true at the start of the most recent action. This is convenient when trying to describe what has changed in the course of the action, but sometimes also when making the action itself happen. For instance:
Completing the set is the past perfect:
which records whether "X has been Y" was true at the start of the most recent action. All these verbs can of course be negated (though "wasn't" and "hadn't" are disallowed as poor style: we use "was not" and "had not" instead). So for example,
is true if the player hadn't visited the Ballroom at the start of the most recent action.
Something we must watch out for is that variables might not have the same values in the past that they have now. As a result, writing conditions such as "if the noun has been open" is a bad idea, because in the past "the noun" very likely referred to something different. It is really only safe to talk in the past tense about definite, fixed things: "if the Great Gates of Kiev have been open" would be fine.
There are two further ways to examine the historical record. Given any condition, we can say
(all of which are synonymous: the words once, twice, thrice, one, two, three, four, five, six, seven, eight, nine, ten, first, second, third, fourth, fifth, sixth, seventh, eighth, ninth and tenth all mean what they obviously should). The result is true if the condition holds now and has held for only one previous spell in the past. A condition holding for, say, fifteen consecutive turns without a break counts as only one "time" – so what we mean by "twice" here is that it is true now, was previously false for a while, and was previously true for a while before that, but no more. In effect, then,
is true if this is the third visit to the Ballroom. We can also say
or similarly "less than", "at least", "at most". It would be more natural, though, to say
The adjective "only" (or equivalently "exactly") can be added to obtain
To recap, this means there have been exactly three visits to the Ballroom in history, whereas
means there have been exactly three visits, the third of which is still going on – an important distinction.
So much for "times" – spells in which a condition is true. We can also test the length of time, in turns of play, that something has been true. Thus:
means that the condition holds now, and held at the start of this turn, at the start of last turn, and at the start of the turn before that. In particular:
will be false if the hat is not currently worn (even if it has been often in the past) and, on the other hand, will be true if the hat has been worn for twenty turns. Here again we can be more specific. These are synonymous:
all requiring that the hat wasn't worn four turns ago. As before, "more than", "less than", "at least" and "at most" so forth can also be used – say, "for at least 21 turns".
A warning: we must be careful when writing something like
since this tests whether it has ever been true that the noun of the then action was open: not whether the current noun-object has ever been open.
Lastly, note that the beginning of play – when (usually) initial text and a banner is printed, followed by a room description – counts towards these counts. In effect, this is a turn: one in which the player compulsorily performs the looking action, rather than being asked for a command. (By convention it is numbered as turn number 0, and doesn't contribute towards the turn count.)
As we have seen, Inform divides up space into individual places called "rooms", and allows us to group rooms together into "regions" if we find that convenient. And Inform also divides time up, into individual turns. These too we can group together: the equivalent of a region is a "scene".
To put this another way, if we think of the interactive fiction as a stage play, then up to now it has simply contained endless dialogue and stage directions – there has been no convenient way to divide up its running time into dramatic episodes, in the same way that a playwright might make Act II take place in the same drawing-room as Act I, but (let us say) six months later, after many things have changed. The script contains cues for one scene to end and another to begin: when those cues are reached, the stage hands rearrange props, actors reposition themselves and so on.
Inform also allows us to create scenes, with cues for them to start and end, and some stage machinery (so to speak) making it easy to move the action on. But interactive fiction is interactive, so the metaphor of the theatre only goes so far. We can have several different scenes going on at once – perhaps with the relevant events taking place in different rooms, which the player is free to walk between. And the player may make a choice which changes the story-line, causing scenes to happen which otherwise would not have happened, and so on. Scenes can even be "recurring", that is, can repeat themselves.
So organising the story-line into scenes is not simply a matter of making a list (Scene 1, then Scene 2, then Scene 3, finis). It is more like a chart in which one scene can lead in several possible ways to others – a sort of map of time, which as we shall see Inform displays in its "Scenes" index.
As usual, we only need to say that something is a scene to make it so:
We conventionally write scene names with capital letters, as this demonstrates.
This works, and shows up in the "Scenes" index, but does nothing. We have given no instructions on when it begins – no cue, in stage-play terms – so it never will begin, and even if it did, nobody would notice since it does nothing. First, to give it a beginning:
In theory any condition can be used to cue the scene – here, it's "the player is in the Station for the third turn" – but it's wise to look for a state of affairs which will last at least a brief time, because scene changes only happen at the start and end of turns. (Something like "…when examining the timetable" may be true only for a part of the middle of a turn, and so go unnoticed.)
Every scene has two rulebooks attached, one at each end, so to speak. These look very like "when play begins" and "when play ends", and work in the same way. Thus:
Thus when the scene begins, our imaginary stage-hands wheel in a steam train; when it ends, they get rid of it again. Note that we know where the player will be at the start of the scene, but by the end he may have wandered off across the fields, so we must be careful not to report something he might not be in a position to see.
When Train Stop begins, we printed some text, but we did this by hand. We didn't need to, because Inform automatically prints out the description of a scene (if it has one) when the scene begins. Scenes can have properties, just like objects, and in particular they have the "description" property. For example, we could write:
which saves us the trouble of writing the rule:
We can also write rules like this which apply to a whole variety of scenes at once. For instance:
Here, instead of naming a scene ("Train Stop"), we've given a description ("a scene which is bright"). When a scene begins, these general rules come before those which name the scene exactly; when it ends, the reverse is true.
But when we test the previous section's example, we find that after a brief wait, the train pulls up: but it never goes away again. We have given instructions on how the scene ends, but not when it ends, and as a result the scene goes on forever once started.
Even with simple story-lines, and this one could hardly be simpler, it is surprisingly easy to overlook something so that the whole story-line is derailed.
The Scenes page of the index is intended to help with this. The Plot section shows all of the scenes and how they are to begin, along with a key to the symbols used on it. One scene always included is "Entire Game", a special scene which, as its name implies, is always being played out. But if we look at the Scene index for the previous example, we will also see our Train Stop scene, and find that it is marked with the red warning symbol for "never ends". Let us fix this:
Note the useful value "time since Train Stop began":
This phrase produces the time since the named scene began, which only makes sense, of course, if it has indeed begun. Example:
This phrase produces the time since the named scene ended, which only makes sense, of course, if it has indeed ended. Example:
The actual times, in case they are needed, can be obtained with:
This phrase produces the time (i.e., the value of the "time of day" variable) at the moment when the given scene began.
This phrase produces the time (i.e., the value of the "time of day" variable) at the moment when the given scene ended.
The testing command SCENES causes Inform to monitor the beginning and ending of scenes, and report on them. For instance:
Scenes are not only useful for changing the setting, by moving items or people around and providing a little narration. We can also make the rules different in one scene from another. For instance, at a sleepy country halt there is no reason why one should not walk across the tracks: but if there is a train in the way, that would be impossible.
Any rule can have the clause "during …" attached, provided that clause goes at the end and either explicitly names a scene, or gives a description of which scenes would match. This is especially useful with "every turn":
We can test whether a scene is happening with the adjective "happening":
This condition is true if the given scene has both begun and ended.
This condition is true if the given scene has not ended (or never started).
This condition is true if the given scene ended at least once.
This condition is true if the given scene has never ended.
We need to be a bit careful: it's possible to set things up so that the Train Stop scene will play out more than once, so "Train Stop is happening" and "Train Stop has happened" might both be true at once.
The kind of value "scene" is one which is allowed to have properties – it has a tick in the "properties" column in the chart in the Kinds index – and this can be very useful in describing scenes. For instance, we could write:
Inform has the adjectives "recurring", "non-recurring" and "happening" all built in to describe scenes, and the above would add "thrilling" and "dull". Moreover, the "during" clause of a rule can give a description of a scene as easily as a specific scene name. For instance:
Let us suppose that somebody gets off the train, after all, so that a second scene follows on.
The effect of this is that they occur in sequence. If we add a third to the chain of scenes:
…we find another chance to fool ourselves: if we check the Scenes index again, we can see the linkages between these scenes, but we also see that Brief Encounter never ends (despite its name). All we have said is that another scene begins where Brief Encounter leaves off, but it never does, so this is moot.
We are allowed to link the beginning or end of any scene to the beginning or end of any other scene. So, for instance:
Thus the two scenes run concurrently, at least for a while. We can also add that:
This can be useful when a large, complicated scene really contains several smaller sub-scenes.
A special exceptional case is that we can have any scene or scenes starting right at the outset:
When play ends, of course, all scenes end, so there is no need to say that.
It is quite allowed for a scene to be linked to several other scenes, and this is useful if several alternate strands of plot are being brought together in a common resolution scene:
and we can also have the same scene beginning when a condition holds. In general, it will begin the first time it gets any chance to do so.
All scenes are ordinarily set up so that they can happen only once. But sometimes we want them to repeat. Suppose the train calls not once only, but every twenty minutes. We could set this up with two scenes linked back to back like so:
The difference here is that these scenes have been declared as "recurring". In all other respects they are the same as any other scene.
Interactive fictions vary considerably in the extent to which the player is allowed to influence the story-line. Sometimes the appearance of making choices is wholly bogus, as only one possible line is given more than lip service. But in other works, the player can radically change the outcome, and whole rafts of plot differ between one person's experience and another's. Inform allows multiple endings to its scenes to make this kind of branching story-line easy to achieve.
Any scene can have up to 31 alternate endings, differentiated by name (unless the Z-machine format has been selected on the Settings panel, in which case, 15). These alternates are created as and when conditions are set for them:
"Ends happily" and "ends wisely but sadly" behave just like "ends". We can have rules "When Brief Encounter ends happily, …" and so forth, in addition to rules "When Brief Encounter ends, …" – if a rule doesn't specify any particular ending, it applies to all of them.
We can also link rules together from these branches, so
With this set-up and that of the previous section, there are now two possible paths through the story:
We might later need to know which of these paths has been taken, and to help with this Inform provides conditions like so:
(For a scene which repeats, note that these conditions apply only to the most recent repetition: and that such conditions are always false if the scene is currently going on. "Brief Encounter did not end happily" will be true only when the scene has finished but in a different way.)
In the part it plays in stories, time is like space. The endings of a scene (along with its beginning) are like the map connections leading out of a room. The Scenes index keeps track of the "map of time" through which these possible story-lines traverse. Some works of IF will have immensely complicated story-lines in only a few rooms, some will have no scenes at all despite a sprawling geography. The Scenes and World index tabs, side by side, show both kinds of map.
Just as Inform uses a simple but practical design for the boundaries between rooms (map connections and doors, that is), it also simplifies transitions between scenes. Scenes are based on states of things: we give circumstances for them to begin or end. There is no phrase with the power to say "make Act II begin right now", so perhaps it is worth explaining why not. The state-based approach was chosen because:
Settings in IF where one revisits the same location but at a different time, or after a dramatic change, have historically been difficult to test properly and prone to mistakes. (The classic example would be where a character killed during Act I reappears unharmed in Act II.) The design of scenes is an attempt to encourage a style of writing which minimises the risk of these accidents.
Since scenes are, in the end, only a convenient way to organise rules, and do nothing that cannot be done by other means, this simplified system of scene changing does not really restrict us.
Phrases are instructions to Inform to do something, or to decide whether something is true or false, or to produce a value, or to say something. Inform has around 350 phrases built-in, and the chapters so far have already defined about 100 of those. In this chapter we'll see some key phrases for organising instructions of what to do, and also see how to define entirely new phrases.
Just to run through the four sorts of phrase with examples:
(a) Phrases to do something. These are the ones used in the body of a rule. For example,
Rules like this begin with a "preamble", the beginning part which tells Inform when or how they apply, and then follow on with a list of instructions – here, just two of them. "move … to …" and "say …" are both phrases. Inform provides about 130 of these built-in. It's actually not quite true that they all do something, because one of them is:
This phrase does nothing at all. It is very occasionally useful to make a rule which does nothing:
(b) Phrases to decide whether a condition is true. These are the ones which can be used in an "if":
Not all conditions come from phrases. For example, "if the front door is closed" and "if Peter is wearing the sandals" have meanings which come from the verbs "to be" and "to wear". Inform provides about 60 built-in conditions, which give a friendly wording for questions which would be lengthy or difficult to write in any other way.
(c) Phrases to decide a value. For example:
produces a number, 4 of course, and can be used whenever a number is expected. Inform provides about 100 built-in phrases like this.
(d) Text substitutions. These are actually just phrases whose definition begins with "To say …". Example:
Inform provides about 60 built-in text substitutions.
The Phrasebook is Inform's collection of recognised phrases, and it can always be browsed using the Index panel of the same name. Even the smallest project has a good-sized phrasebook, since it contains all of the built-in phrases. But most projects also define new phrases of their own.
Here is a simple definition of a new phrase:
Inform allows us to use whatever conventions of layout we prefer, but it's customary to use indentation like this, dividing off the preamble from the phrases which follow. As can be seen, definitions of new phrases look very like rules.
What makes this definition a simple one is that the wording is fixed. The only way to use this would be from another phrase or rule, like so:
In the next section we'll see how to give more complicated definitions which, like "move … to …", allow for the wording to change with the circumstances.
In this section, let's make the following new phrase:
This does very little, of course, but it does allow the wording to be different each time the phrase is used:
and our single definition covers all of these possibilities. The bracketed part of the definition, "(item – an object)", tells Inform to expect an object in that position, and Inform enforces this carefully. So this definition might tell Inform what "admire the barricade" means, but not what
mean. Unless some other definition sorts the matter out, Inform will reply to uses like this with a Problem message:
, but '63' has the wrong kind of value: a number rather than an object.The object does not need to be named literally, but can be anything which works out to be an object: for instance,
which Inform allows because "noun", here, is a name for the object which is being acted on.
Inform decides which definition to apply in a process called "pattern matching".
The bracketed part of the example definition has the form "(name – kind)". The definition only applies if the text supplied agrees with the "kind" part – for instance, the diamonds agreed with "object", but 63 did not. If the definition does apply, then the Inform works through the rest of the phrase using "name" to mean whatever value matched. For example:
When this phrase is followed, "box" means whatever open container the pattern-matcher found when it was called for. For example, if Inform reads
then it acts on this by following the definition of "slam shut …", using the Dutch armoire object as the value of "box", so it prints:
and renders it closed.
In fact any description can be given in the definition, and that includes a single, specific value. For instance, we could define:
which would withhold this unlucky bounty. That would mean that:
would each produce uncontrollable shivers, because Inform uses the definition applying to the number 7; but
would increase the score by 6. In general Inform always follows the principle that more specific definitions take priority over more general ones. So although the definitions:
both apply to the case of "grant 7 points", Inform uses the second, because it's the more specific of the two possibilities.
Sometimes it will not be possible to tell if the value supplied meets the requirements until the story is actually playing. If, at run-time, no definition fits some phrase which has to be carried out, a run-time problem message is produced.
Finally, and more straightforwardly, we can specify variations in wording using slashes between alternative words in a "To …" definition. For instance:
allows the final word to be either "point" or "points". Slashes like this can only be used with literal words, not bracketed values, and give alternative forms only of a single word at a time; the alternative "--" means "no word at all", and thus makes it optional:
makes "grant 3" do the same as "grant 3 points".
If we need more variation than that, we should make more than one definition.
We've already seen the SHOWME command, which can be typed into the Story panel to look at the state of something, usually a thing or room. SHOWME is a testing command which has no effect once the work is released; eventual players can't use it.
Inform also has a phrase called "showme", which works in much the same way:
This phrase is intended for testing purposes only. If used in a story file running inside the Inform application, it prints a line of text showing the given value and its kind; in a Released story file, it does nothing at all. Example:
produces
More usefully:
Now, every turn, we get a line in the story's transcript like so:
Inform uses the quotation marks and equals sign to show that it had to do some work to find the answer. "score" wasn't a constant value – it was a variable, and Inform had to look up the current value.
"showme" is a convenient way to see what's going on inside a phrase which isn't behaving as expected, or to find out the kind of a value. Here are some trickier examples. Suppose our design includes:
If we then try this:
we get, when the story starts up,
Why is this an "object", when we know that the key is actually a "thing"? After all, if we "showme key" instead, we get:
The answer is a little technical: it's because Inform guarantees that the matching key is always an object, but not that it's always a thing – it just happens to be a thing at the moment. There's not really a contradiction, because a "thing" is a kind of "object", so in fact the key is both. If we try "showme matching key", we get something like this:
which is even more technical – people never need to print the names of abstract property names during play, so Inform doesn't provide any good way of doing it. It is reduced to printing out an internal ID number ("property 23") instead of the name ("matching key"). This can't be helped: "showme" is a way to lift the lid and see what's going on inside Inform's machinery, and some of the corners are dark.
All the same, "showme" can be very useful in tinkering with rules to make them work properly. It prints nothing at all in a Release version of a project, so it's impossible for these private notes to be shown accidentally to our eventual readers.
A variety of "conditions" have already appeared in this documentation. A condition is a phrase which describes a situation which might be true, or might be false, and examples might include:
These are all examples of sentences, formed by putting nouns either side of a verb, and clearly a wide range of conditions can be written this way. But there are also a few special conditions built into Inform which have a fixed wording, and test questions difficult to address with ordinary sentences. For instance:
This condition is true if the player currently has no light to see by. Note that the test is more complicated than simply testing
since the player might have a torch, or be inside a cage which is itself in a dark room, and so on.
Another example of a condition not easily written as a sentence is:
This condition is unusual in doing something and not simply making a silent check: it waits for the player to type YES (or Y) or NO (or N) at the keyboard, and then is true if the answer was yes. Example:
Whether it's put to the player like this or not, testing a condition is really asking a question, and there is always a yes/no answer. In Inform this answer is not usually a value (unlike in some other computer programming languages), but it can be made into one.
Firstly, we need a special kind of value to hold answers like this. It's called "truth state", and it has just two possible values, written as "true" and "false". We then need:
This phrase converts a condition into its result as a value, which is always either "true" or "false". Example:
produces the truth state "false". This is mostly useful for storing up results to look at later:
and then subsequently:
As another example, in most stories this:
…will produce a line:
In short, "truth state" is a kind of value like any other. That means it can be the kind of a variable:
and it can similarly be used in table columns, lists, or anywhere else where values are allowed.
Inform's most powerful phrases are those which control the others, making them repeat, or be skipped.
This phrase causes the single phrase, or block of phrases, following it to be obeyed only if the condition is true. (If the condition must contain a comma for some reason, the block form should be used.) Example:
The sense of an "if" can be reversed by using the word "unless" instead:
This phrase causes the single phrase, or block of phrases, following it to be obeyed only if the condition is false. (If the condition must contain a comma for some reason, the block form should be used.) Example:
"Unless" is clearly unnecessary, but it can be a good way to make the source text easier for humans to read.
As we have seen, there are many different forms of condition in Inform. They usually take a form quite like an assertion sentence, except that they're questions and not statements of fact. For example:
Questions like this are checked by Inform to see if they make sense. The following doesn't, for instance:
This produces the baffled reply:
, I can't determine whether or not '10 is a door', because it seems to ask if a number is some sort of door.In practice it is not enough to apply "if" to a single phrase alone: we want to give a whole list of phrases to be followed repeatedly, or to be followed only if a condition holds.
We do this by grouping them together, and there are two ways to do this. One is as follows:
Here we group two phrases together under the same "if". Note that the comma has been replaced by a colon, and that the indentation in the list of phrases shows how they are grouped together. In the example above, the source moves two tabs in from the margin; the maximum allowed is 25.
Indentation is the convention used in this manual and in the examples, but not everybody likes this Pythonesque syntax. So Inform also recognises a more explicit form, in which the beginning and ending are marked with the words "begin" and "end":
(Pythonesque because it's a style popularised by the programming language Python, named in turn after "Monty Python's Flying Circus".)
We often need code which does one thing in one circumstance, and another the rest of the time. We could do this like so:
but this is not very elegant, and besides, what if the action we take when N is 2 changes N so that it becomes something else?
Instead we use "otherwise":
This phrase can only be used as part of an "if …:" or "unless: …", and provides an alternative block of phrases to follow if the first block isn't followed. Example:
When there is only a single phrase we can use the shortened form:
We can also supply an alternative condition:
At most one of the "…" clauses is ever reached – the first which works out.
If the chain of conditions being tried consists of checking the same value over and over, we can use a convenient abbreviated form:
This phrase switches between a variety of possible blocks of phrases to follow, depending on the value given. Example:
One alternative is allowed to be "otherwise", which is used only if none of the other cases apply, and which therefore guarantees that in any situation exactly one of the blocks will be followed.
This form of "if" layout is not allowed to use "begin" and "end" instead of indentation: it would look too messy, and would scarcely be an abbreviation. It is also not allowed to use "unless" instead of "if", because the result would be too tangled to follow.
The next control phrase is "while", which has the form:
This phrase causes the block of phrases following it to be repeated over and over for as long the condition is true. If it isn't even true the first time, the block is skipped over and nothing happens. Example:
We must be careful not to commit mistakes like the following:
which, as sure as eggs is eggs (which is very sure indeed), writes out
forever. (Inform won't prevent this: we will find out the hard way when the story is played.) While we would probably never write anything so blatant as that, the mistake is all too easy to commit in disguised form. We should never design a loop, as repetitions like this are called, without worrying about if and when it will finish.
As with "if", we can use "begin" and "end" instead of a tabulated layout if we want to --
(The "begin" of an "if" must of course match an "end if", not an "end while", and so on.)
Experience shows that it is much more legible to lay out "while" loops as blocks, even in these rare cases when only a single phrase forms the body of the block.
The other kind of loop in Inform is "repeat". The trouble with "while" is that it's not obvious at a glance when or whether the loop will finish, and nor is there any book-keeping to measure progress. A "repeat" loop is much more predictable, and is more or less certain to finish.
There are several forms of "repeat", of which the simplest is similar to the old FOR/NEXT loop from the home-computer programming language BASIC, for those with long memories:
This phrase causes the block of phrases following it to be repeated once for each value in the given range, storing that value in the named variable. (The variable exists only temporarily, within the repetition.) Example:
This, and runs through the given phrases ten times. Within those phrases, a special value called "counter" has the value 1 the first time through, then the value 2, then 3 and so on up to 10. (It can of course be called whatever we like: this is only an example.) The range can be from any kind where ranges make sense – anything on which arithmetic can be done, so for instance
and also any enumeration:
We are allowed to "nest" loops, that is, to put one inside another.
If we then write
then the result is
Thus the innermost phrase, the say which mentions "y", happens 25 times.
Whenever dealing with numbers in Inform we may need to remember that if the Settings for the project are set to use the Z-machine, the range is restricted to -32768 up to 32767. Repeating with a counter up to exactly 32767 is hazardous, because the counter can never break through this barrier: it's infinity, so far as Inform is concerned, and that can cause the repetitions to go on forever. (On Glulx, numbers can be very much larger.)
Inform is not used very much for numerical work, so the kind of repeat loop described in the previous section is not much used. Inform's natural domain is really the world of things and rooms, so the following kind of repeat is much more useful.
This phrase causes the block of phrases following it to be repeated once for each value matching the description, storing that value in the named variable. (The variable exists only temporarily, within the repetition.) Example:
If there are no containers, or they are all closed, the phrases will not be followed at all. Inform will issue a Problem message if the range of the loop may be infinite: for example, it won't allow:
On the other hand it will allow:
which repeats 1440 times, starting with T at midnight and finishing at 11:59 PM. See the Kinds index for which kinds of value can be repeated through.
As with counting the "number of …" objects satisfying some property, we can run through a wide variety of possibilities – any description whose range is possible for Inform to search. For example:
The following lists the whereabouts of all men in lighted rooms:
One small note of caution: if what the "repeat" loop does is to change the things being repeated through, changing in particular whether items not yet reached will qualify to be repeated through, the results can be unexpected. Rather than writing "repeat with X running through D", it may be safer to try "while there is D (called X)", though note that this will only finish if X is always changed so that it no longer qualifies.
So "repeat" and "while" phrases cause a block of other phrases to be repeated, over and over. The number of repetitions and the flow of "control" has so far been controlled only by the way the original loop was described.
But in fact it's also possible to change this from inside the block being repeated, using these:
This phrase can only be used inside a "repeat" or "while" block, and causes the current repetition of the block to finish immediately. That either means the next repetition begins, or (if we are already at the last one) the loop ends too. Example:
produces the text "1 2 3 5 6 7 8 9 10 ", with no "4" because the "say" phrase was never reached on the fourth repetition.
In Monopoly terms, "next" is "Advance to Go" rather than "go directly, do not pass Go, do not collect $200" – the next iteration begins with the variable, if there is one, having cleanly moved on to the next value, just as if the loop had been run through in the normal way. ("Next" is called "continue" in a fair number of programming languages, so Inform issues a specific problem message to help people who forget this.)
This phrase can only be used inside "repeat", "while" block, and causes both the current repetition and the entire loop to finish immediately. Example:
produces the text "1 2 3 4 5 6 ", with nothing after "6" because the loop was broken at that point. The "say" wasn't reached on the 7th repetition, and the 8th, 9th and 10th never happened.
Now that it's possible to define phrases where different things are done in different circumstances, we sometimes want to halt early. This is what "stop" is for.
This phrase causes the current rule to end immediately. It is most often used in the definition of other phrases:
In the case when the score is 0, the "stop" ends the phrase immediately, so that the subsequent text is printed only if the score is not 0.
"Stop" can also be used in action rules, though this is not very good style – it's clearer to use "stop the action", which is exactly equivalent.
There are sometimes several slightly different ways to perform a given task but which have substantially the same definition. In the following example:
…a phrase has been set up which can be used in three ways:
Note that commas must be used to divide these "phrase options" from the rest of the text of the phrase. Within the definition of the phrase, the option's name is a valid condition, and
tests whether it is set; we can also test if it is not set using:
A more substantial example from the Standard Rules is given by a phrase used mostly for internal, technical reasons:
This phrase produces a list of all things whose holder is the given object, according to Inform's traditional conventions for room descriptions and inventory listings. Example:
Where this is possible, it's generally better to use "[list of things in …]" instead, which produces the same result in an acceptable way for the middle of a sentence.
Note that this phrase is allowed to have multiple options specified, whereas "go hiking" above was not: this is because it was defined thus:
The significant difference is the word "and/or" instead of "or", which signals that more than one option can apply at a time.
A variable, as we have seen, is a name for a value which changes, though always remaining of the same kind. For instance, if "target" is a number variable (or "number that varies") then it may change value from 2 to 4, but not from 2 to "fishknife".
To make complicated decisions, phrases often need to remember values on a temporary basis. We have already seen this for the counter in a "repeat" loop, which exists only inside that loop, and then is no longer needed.
We can also make temporary variables using "let":
This phrase creates a new temporary variable, starting it with the value supplied. The variable lasts only for the present block of phrases, which certainly means that it lasts only for the current rule. Examples:
The kinds of these are deduced from the values given, so that, for instance,
produces
The variable name should be a new one; if it's the name of an existing one, then the kinds must agree. So:
is a legal combination, because the second "let" simply changes the value of the existing "outer bull" variable to a different number.
This phrase creates a new temporary variable of the given kind. The variable lasts only for the present block of phrases, which certainly means that it lasts only for the current rule. Example:
The variable created holding the default value for that kind – in this case, the number 0. A handful of very obscure kinds have no default values, and then a problem message is produced. Inform also disallows:
because temporary variables aren't allowed to have kinds more specific than "object". (This is a good thing: suppose there are no vehicles in the world?) It's quite safe in such cases to use
instead, which creates it as the special object value "nothing".
Temporary variables made by "let" are only temporarily in existence while a phrase is being carried out. Their values often change: we could say
for instance, or indeed we could "let x be 10" and then "let x be 11". But although we are allowed to change the value, we are not allowed to change the kind of value. The name "x" must always have the same kind of value throughout the phrase to which it belongs, so the following will not be allowed:
(The difference between using "let" and "now" here is that "let" can create a new temporary variable, whereas "now" can only alter things already existing: on the other hand, "now" can change many other things as well, whereas "let" applies only to temporary variables.)
We can create new conditions by defining a phrase with "to decide whether" (or equivalently "to decide if"):
If the player is indeed in darkness, the decision is "yes" because the "decide yes" stops the process right there. We can now write, for instance,
In fact, "danger lurks" is now a condition as good as any other, and can be used wherever a condition would be given. Rules can apply only "when danger lurks", for instance.
This phrase can only be used in the definition of a phrase to decide whether a condition holds. It ends the decision process immediately and makes the condition true.
This phrase can only be used in the definition of a phrase to decide whether a condition holds. It ends the decision process immediately and makes the condition false.
We can also supply definitions of adjectives like this. So far, new adjectives have been defined like so:
If we want to give a definition which involves more complex logic, we can use a special form allowing us to make arbitrary decisions. In this longer format, the same definition would look like so:
Here "it" refers to the supporter in question. Note that there are now two colons in this sentence, one after "Definition", the other after the clause being defined. But that apart, it's a phrase like any other: it must end in "yes" or "no" just as the "danger lurks" example must. "Decide no" and "decide yes" are needed so often that they can be abbreviated by leaving out "decide":
A condition is a yes/no decision, but we can also take decisions where the result is a value. Suppose we want to create a concept of the "grand prize", which will have different values at different times in play. Each time the "grand prize" is referred to, Inform will have to decide what its value is, and the following tells Inform how to make that decision:
Note that we have to say what kind the answer will be: here it's a kind of thing called "treasure" (which we're supposing has already been created), and as it turns out only two treasures are ever eligible anyway (we're also supposing that the plover's egg and the silver bars are treasures already created, of course). And note also that the phrase must in all cases end with a "decide on …" to say what the answer is:
This phrase can only be used in the body of a definition of a phrase to decide a value. It causes the calculation to end immediately, with the outcome being the given value, which must be of the kind expected. Example:
Now that we have "grand prize" created, we can use it just as we would use any other value, so for instance:
As this is something of a dialect difference between English speakers, "what" and "which" are synonymous here, i.e., we could equally well write something like:
(A phrase to decide if something-or-other is exactly the same thing as a phrase to decide a truth state, and indeed, if we want to then we can use "decide on T", where T is a truth state, in its definition. For instance:
"Decide on true" is exactly equivalent to the more normally used "decide yes", and of course it is optional. The last line is more interesting since it effectively delegates the answer to another condition.)
A point which has come up several times in recent chapters is that enumerated kinds of value have a natural ordering. For example, if we write:
…then we not only have seven possible values, we have put them into a sequence, in order of their naming. We can't perform arithmetic on colours, of course, but we can perform comparisons on them. Thus "red < yellow" is true, while "green >= violet" is not. (More on comparisons in the chapter on Numbers and Equations, which also covers arithmetic.)
It's also sometimes useful to get at the sequence directly. First, the two ends:
This phrase produces the first-created value of the given kind, which should be an enumeration. Example: if we have
then "first value of colour" is red.
This phrase produces the last-created value of the given kind, which should be an enumeration. Example: if we have
then "last value of colour" is violet.
And now how to step forward and back:
This phrase produces the next-created value of the given kind, which should be an enumeration. Example: if we have
then "colour after orange" is yellow.
This phrase produces the previous-created value of the given kind, which should be an enumeration. Example: if we have
then "colour before blue" is green.
Actions are impulses to do something, which arise sometimes through typed commands:
and sometimes through "try" phrases occurring in other rules:
Every action either succeeds or fails, though failure may not be a bad thing (something better may have happened). Besides any rules applied in the source text, actions are subject to basic realism rules. A general rule ensures that actions are rejected if the actor would need to touch something which is out of reach, or see something which is invisible; and a couple of hundred other built-in rules police individual actions. For instance, if the ACTIONS testing command has been used to switch monitoring on, then:
Actions generated by "try" phrases are allowed to run "silently", which means that if nothing out of the way happens and they succeed, then nothing is printed. For instance:
There are many ways to impose extra rules on actions, and we have seen three main kinds: Before rules, intended so that preliminary activities like the one above can happen before the action is tried; Instead rules, which block or divert the intention, or may cause something spectacularly different to happen; and After rules, which allow for unexpected consequences after the action has taken place.
The following flow chart shows the natural course of events when Inform deals with a new action – a "taking" action in the case drawn. For quite a long time, the action may still fail, and it may be that nothing actually happens: but eventually a deciding line is crossed, and once that happens the action will certainly succeed.

The coloured boxes on this chart represent "rulebooks", that is, collections of rules with a common purpose. The orange boxes for Before, Instead and After were covered in the Basic Actions chapter, but the blue boxes are new. The orange boxes are where we put rules to handle unusual situations, or unexpected events: special rules to cover the opening of a container which happens to be booby-trapped, or walking through a doorway into a room where a surprise party is about to be sprung.
Blue boxes hold the mundane, everyday rules – the generic ways that particular actions behave. Every action provides these: "Check" rules, to see if it makes sense – for instance, to see that the player is not trying to take his or her own body, or a whole room, or something he or she already has; then "Carry out" rules, to actually do what the action is supposed to do – in the case of taking, to move an object into the player's possession; and finally "Report" rules, which tell the player what has happened – perhaps printing up "Taken."
When we create a new action, we add a new column to the blue rows in this diagram. As we shall see, we can also put new rules into the existing blue boxes: for instance, if we wanted to increase physical realism by forbidding the player to carry more than a certain weight, we would want to add a new "check taking" rule, and this is entirely legal.
In subsequent chapters, we will see ways to intervene at almost every point in the above diagram – from how "Can we see or touch things?" is reckoned, to each and every individual rule in all of these books. Action-processing may be the single most important thing Inform does, so the system is designed to be immensely flexible. On the other hand, that does make it a lot to take in at one look. Newcomers should probably concentrate on "Instead" and "After" as the basic tools for designing the situations turning up routinely in interactive fiction. There are guidelines at the end of this chapter offering advice on which tricks to use when it comes to more complicated needs.
So far, all actions have been carried out by the player: which is fine for exploring the passive world of an empty warehouse, but less good for a drama in which other characters have to be contended with. In fact, an action can be carried out by anybody – by any instance of the "person" kind, that is, which includes all the men, women and animals in the story, and not only the player.
In interactive fiction, players conventionally ask other characters to do something with commands like so:
Clearly "will, go west" should not produce the same action as "go west", because a different person will be trying it: this person is called the "actor", and while the actor is ordinarily the player, here it is the character called Will. Inform distinguishes these two actions like so:
As a result, we can write rules like so:
To write rules like this, we sometimes want to generalise about who is supposed to do the deed. To do this we can refer to "person asked", just as the "noun" stands for whatever noun was typed:
So if the player types "Algy, take sandwich", the "person asked" would be Algy; the "noun" would be the sandwich; and there would be no "second noun".
"Asking … to try …" actions run through their Before and Instead rules like any other actions, but then (if no rule has intervened) something different happens: Inform has to decide whether the person asked consents to try the action or not. By default, the answer is always no, and text like the following will be printed:
However, we can intervene to make the answer "yes", using a special kind of rule which produces a yes/no answer. The following examples show how we can give broad or narrow permission, as we choose:
Such a rule can either declare that "persuasion succeeds", or that "persuasion fails", or make no decision and leave it to another rule to say. If it decides that persuasion fails, it is also allowed to say something, describing why: in that event, the standard message ("Will has better things to do.") is suppressed. For example,
The following rule, which is really only suitable for testing, makes everybody infinitely obliging:
Supposing that Will does decide to cooperate, a new action is generated:
and this is then subject to all of the usual action machinery. For instance, we could write a rule such as:
So in this case the new action ("Will going west") failed: but the original action, "asking Will to try going west", is still deemed to have succeeded – after all, Will did try. To put it more formally, "asking X to try A" succeeds if the persuasion rules succeed, and otherwise fails.
Note also that "Instead of…" rules written for other people will be treated by Inform as failures, even if we write something like
and thus may produce unsatisfactory results such as
If we wish to write new successful actions for another character, we will need to create appropriate carry out and report rules for them: these will be explained in the sections to follow.
(Finally, note that the mechanism Inform uses to see if we have printed a refusal message of our own, in the event of persuasion rules failing, can be fooled if we write a persuasion rule explicitly ending with a "[paragraph break]" text substitution.)
Suppose, finally, that Will not only consents to try the action, but it also survives its passage through Before and Instead rules. What happens then? In principle, what happens to Will is exactly what would have happened to the player in his place. For instance:
If on the other hand Will's attempt is frustrated because one of the checking rules stops him, then Will's action fails. For instance, if Will tries going northeast but there is no room to northeast, one of the rules checking the "going" action will stop him. We will then see this:
This is rather a generic message, and we may want something more interesting. We can provide that using yet another special kind of rule:
Even that is still a little generic, though, because it treats all of the various ways that "going" can fail as the same. If we have ACTIONS switched on, we can see what goes on behind the scenes when we ask Will to walk into a door:
(The "(1)" lets us know that a new action is starting during the old one, and before the old one finishes: sometimes we go up to three or four deep, though seldom more in practical cases.) We can now rewrite the "unsuccessful attempt" rule like so:
The value "reason the action failed" is set to whichever checking rule threw out the action which Will tried. The names of these rules try to be self-explanatory – at any rate, those with gnomic names are not useful for this sort of thing, and can be ignored – and can be found out either using ACTIONS or by consulting the Actions index.
Finally, note that "unsuccessful attempt" rules apply only when the person in question is being asked to perform the action by somebody else – as in the examples above.
The player's actions happen not only when he types a command, but can also happen spontaneously as a result of a "try" phrase.
The latter might, of course, result in Will trying going west: or it might not – that depends on the persuasion rules. But as the author, we have the ultimate powers of persuasion, and can make Will act in any way we like, without asking:
Nobody in the simulated world requested this: it is an impulse felt by Will alone, so that – from the player's point of view – Will is acting spontaneously. The player need not be anywhere nearby, and may never know what happened. Recall that when actions work their way down through the flow-chart, they are stopped before reaching the "report" stage – when the player is told about them – if they are running "silently". This is also where Inform stops an action which is not witnessed by the player.
To repeat a point in the previous section: "unsuccessful attempt" rules do not apply to actions which the author has caused to happen, using "try". When such actions fail, they invoke no special set of rules. Indeed, when "try" causes somebody other than the player to try an action, nothing will be printed to report back on success or failure. If Will can't go west, that's his problem.
Note that the text "try Will going west" involves the actor's name immediately placed next to the action he is to try, which in a very few cases might cause ambiguities. If the actor's name contains a participle like "going" – say, if Will's full name turned out to be Mr Will Going – then we would have to write out the action name in full, using "trying" to clarify matters:
It is not often that we need to create new actions, but a large work of interactive fiction with no novelty actions is a flavourless dish. Here we shall create an action for photographing things.
In theory that text is already sufficient to make the new action, but what we have so far is rudimentary to say the least. The two qualifications give Inform the useful information that we cannot photograph in the dark, and that we need to be photographing something – not, as in the case of waiting or taking inventory, acting without reference to any particular thing external to ourselves.
The word "visible" here tells Inform that we do not need to be able to touch the thing in question: a line of sight is good enough. These two stipulations were necessary because the default arrangement is that any object must be in touching range, and that most actions can be performed in darkness. (Also, note that if you invent an action which needs to apply to directions like "north" or "south", you need to make this apply to visible things, because the object used inside Inform to represent the idea of "north" can be seen but not touched. So for understanding purposes, "visible thing" is understood as meaning any visible thing or direction: it's more general than "thing", not more specific.)
Occasionally, when writing general rules about actions, it can be useful to find out what the current action's requirements are: the following conditions do what they suggest.
This condition is true if the action being processed is one whose (first) noun is an object which needs to be touchable by the actor. For example, it's true for "taking", but false for "examining".
This condition is true if the action being processed is one whose second noun is an object which needs to be touchable by the actor. For example, it's true for "putting the brick in the sack", but false for "throwing the brick at the window".
This condition is true if the action being processed is one whose (first) noun is an object which needs to be carried by the actor. For example, it's true for "dropping", but false for "taking".
This condition is true if the action being processed is one whose second noun is an object which needs to be carried by the actor.
This condition is true if the action being processed is one which can only be performed if the actor has light to see by. For example, it's true for "examining", but false for "dropping".
As further examples, here we create "blinking" and "scraping X with Y". Note the use of "it" to indicate that the name of an object should go here.
The photographing action now exists, but with two provisos: (a) it never happens, because Inform does not know what commands by the player should cause it, and (b) even if it were to happen, nothing would follow, because Inform does not know what to do. (There are no check, carry out or report rules yet.)
The first problem is easily overcome:
We will return to the whole subject of parsing, as this process of understanding the player's commands is called, later. But this gives the gist of it.
Understand for the full story.
Our three example actions can be recognised in play using the following:
The last of these examples shows why Inform does not risk generating this automatically: English is so full of irregular verbs. Inform could have guessed "blink" and "photograph", but might then have opted for "scrap" instead of "scrape".
Inform does risk automatically generating the past participle of an action. (Many past participles are never needed, so the stakes are lower if Inform gets this wrong.) What usually happens is that the "-ing" is replaced with "-ed", thus photographed, blinked, scraped – but Inform has a dictionary of some 460 irregular exceptions, such as caught, fled, crossbred, taken, woven. So with luck Inform will guess correctly. If not, we can get around this like so:
The normal behaviour of an action is specified by its three associated rulebooks – check, carry out and report. In the case of our "photographing" example, these rulebooks will be:
So far we have not really gone into the business of what rulebooks are, and we don't do so here either – suffice to say that we can now create whatever rules we need:
In fact, writing "a check photographing rule" is over-formal. We can more simply label our rules like so:
For the sake of brevity, photography has no interesting consequence (no points to be won, no film to use up), so there are no carry out rules here. Note the way we used the word "instead" once again to stop actions in their tracks.
We can continue to add rules at any point, and a classic thing that happens when testing a new work is that the designer realises there is a case which has not been thought of:
For some complex situations, it can be useful to keep track of a few values throughout the processing of the action. This is not an everyday occurrence: in the Standard Rules, for instance, only two or three out of 90 actions need to do this. But suppose we want to write a more deluxe version of our "photographing" action. This time, rather than having a single thing called the "camera", we will provide a whole range of possible cameras, varying in quality:
And we will want the photographing action to have the player use the best-quality camera which comes to hand. We will give the action a variable called the 'camera photographed with', thus:
Every action's variables must be named differently from those of all other actions, because there are some "before" rules (for instance) which take effect for many different actions, and which might need access to any of their variables. So action variables should be named in a way marking out to which action they belong. The best way to do this is to include the past participle of the action name – just as "camera photographed with" contains the past participle "photographed" of the action "photographing".
This value is created when the action begins, and disappears when the action ends. (If the action should happen a second time before the first time was completed, a second copy of the value is created, leaving the original undisturbed.) When the action begins, the value starts out as something neutral – so if it is a number, it starts out as 0, if a text, it starts out as the blank text "", and so on. Here it is an object, so it starts out as nothing – the value meaning no object at all. But of course we want to give it a value ourselves. We can do that using the "setting action variables" rulebook. For instance:
The "setting action variables" rulebook is run through before even the before rules, and it has no power to stop or change the action. Its rules should say nothing and do nothing other than to set rulebook variables like this one. Note that it is intended to work for any actor, not only the player: so rather than referring to the player as the performer of the action, we need to write "the actor", as in the example above. (See subsequent sections for more on actors.)
We can now write rules such as:
Only rules to do with the photographing action – before, instead, after, check, carry out, or report rules, and so on – are allowed to see the 'camera photographed with' value: it's the private property of the action.
A further elaboration allows us to make rules about photographing neater to write. If we create our variable like so:
…then we are now allowed to add an optional 'using …' clause onto a description of the action. The clause has to be introduced with a single word: here, it's 'using'. For instance, we could write rules such as
(This is the method used by the Standard Rules to attach optional clauses such as 'to', 'with' and 'through' to the going action.)
The "photographing" action now works very nicely when the player does it. But not when others try. Suppose that neither the player, nor Clark Gable, is holding the camera:
An uncanny silence. What has happened is that the rules written so far are all implicitly restricted to the player only. This is because when we write -
the action is "photographing", not "Clark photographing". In the next few sections we shall see how to make the rules work nicely for everybody. This is a little bit harder, so it should be noted right away that in many projects there is no need. In a story which has no other characters who succumb to persuasion, for instance, only the player will ever try the action.
If we want to impose the restriction about carrying the camera on other people, we need a rule like the following:
Implicitly, that "someone" excludes the player. Note that we say nothing in this rule, stopping the action without a word: after all, Clark might well be out of sight when trying this. If he is within sight, then we read:
We saw before that Inform's built-in rules all have handy names (the "can't drop what's already dropped rule", and such), and that these are useful when writing better "unable to…" messages. So for a deluxe version, we end up with:
And now, with ACTIONS on, we find that:
which means that we could have, say,
Report rules for the player's actions are easy to write, and for many actions, they are not much harder for other people either:
But once other people are involved, we have to go to some trouble to get all of the possibilities right. Here is a case which did not immediately occur to the author of the "going" action, for instance:
We said before that report rules are skipped if the action is running "silently", or if the action is one that the player does not witness. But that is also a tricky concept. Inform's doctrine is that you witness an action if you can see any of the actor, the noun or the second noun at either the beginning or the end of the action; except that being able to see a backdrop does not count. Thus if Clark Gable, in Beverly Hills, photographs the Hollywood sign then we do not witness this from Sunset Boulevard merely because we, too, can see the Hollywood sign.
While the report rules for actions by the player must actually report something, report rules for other people's actions are under no such obligation. For instance, if Clark unlocks a door from the other side to the player, then this counts as an action that the player witnesses – and after all, it could be argued that the player should hear the key turning in the lock – but in fact the standard rules for reporting locking choose to say nothing.
In the previous sections, we created a new action by providing one set of rules for the player and another for anybody else who might try to perform it. These rules began with action descriptions in one of the following forms:
The first form implies that the player must be performing the action: the second allows for any person matching P to be the action, except that this person must not be the player. That means that all rules seen so far either affect only the player, or only other people.
This is often convenient, but sometimes we need to set up a complicated action which really does work in the same way for every actor – for instance, the built-in Inform actions provided by the Standard Rules aim to do this. We can write such rules thus:
Here the rule applies to anyone who tries taking a container, player or not. Inside such a rule, the special value 'the actor' is the person performing the action. For instance, the Standard Rules include this one:
The actions seen so far are all impulses causing the protagonist inside the fictional world to do something, or at least try to. But when the player types "quit" or "save", that is not a request for anything to happen in the fictional world: it is an instruction to the program simulating that world. In fact, just the same, such requests are treated as actions, but of a special category called "out of world" actions. They do not cause time to pass by, so the turn counter does not advance, nor does this command cycle count as a turn at all; and they are altogether exempt from "Before", "Instead" and "After" rules. Only the player is allowed to try them.
We can also create new out-of-world actions. Suppose we want a dialogue like so:
Here is a complete implementation:
It is important not to use "out of world" actions for anything affecting what goes on in the fictional world, or realism will collapse, and action-processing may also fail to work in the usual way. "Out of world" actions should be reserved for providing commands like ROOMS, which monitor events rather than participate in them.
The flow chart back at the start of this chapter shows that, early on in processing an action (between Before and Instead), Inform asks the question "Can we see or touch things?" This is where it enforces the requirements in the action's definition:
Seeing and touching are two different questions, which Inform answers in different ways. We shall see ways to modify or entirely alter what can be seen using the "deciding the scope of something" activity when we get to the Understanding and Activities chapters, and later in this chapter we will change the definition of touchability. What both have in common is that they are complicated questions, affected by the circumstances. We cannot simply declare that the player can touch a given lever, or can see in a given room: we must arrange for there to be no barriers between the player and the lever, or for there to be a light source in the room.
An example of rules applying to given objects is provided by the way that Inform decides whether the player can reach something or not. For instance, suppose the following:
The player will be able to examine the granule but not to take it, as that would require reaching through glass. Suppose the player does type TAKE GRANULE: then Inform looks for potential barriers between the player and the granule, and of course finds the conical flask. If, as in this case, the thing to be touched is on the inside, then Inform asks the "reaching inside" rules for permission. There are two reaching inside rules built in to Inform:
and in fact the second of these rules will cause the taking action to fail, because the conical flask is a closed container. (The other rule has to do with a player in one room able to see another room through, say, a telescope – merely having a line of sight doesn't give the ability to reach into the frame.)
Symmetrically, Inform also has "reaching outside" rules, used if the player is inside something and wants to reach an object in the wider room. (From a bed, probably yes; from a cage, probably no.) This ordinarily contains just one rule:
To recap, actions are created like so:
Actions can involve up to two different things. We can place additional requirements on any of these things by describing them as a "visible thing", "touchable thing" or "carried thing". (If we simply say "thing" or "things", as in the second example, Inform assumes the requirement to be "touchable".) These three conditions are increasingly strong:
- To be "visible", something needs only to be possible to refer to by the player, which in practice means that it must be visible to the player-character. The noun or second noun produced by any action resulting from a command at the keyboard will always satisfy this minimal condition.
- To be "touchable", the player-character must be able to physically touch the thing in question: this normally means that it must be in the same room, and there must be no physical barriers in between.
- To be "carried", the player-character must (directly) carry the thing in question. (But if the player types a command using an action requiring something "carried", like WEAR HAT, the thing in question – the hat – will sometimes be picked up automatically. This is called "implicit taking", and results in text like "(first taking the top hat)" being printed.)
If an action involves two things, they need not have the same requirement as each other:
Thus to "wave magic wand at banyan tree", the player must be holding the wand, but need only be able to see the tree.
Note one special case. Requirements on touchability are waived in the case of "try" actions applied to people other than the player where the things they would need to touch are doors or backdrops. (This is a compromise to avoid difficulties arising from the ambiguous locations of such items.)
The question of what the player can, and cannot, reach to touch is important in interactive fiction. It contains some of the subtlest ideas in the model world, though they often go unnoticed. For instance, if a key is on a shelf which is part of a closed box, can we reach for the key? This comes down to whether the shelf, described only as "part of" the box, is on the inside or the outside: and in fact, because it cannot know which is the case, Inform allows either. So in general it is best to regard "parts" as being exterior parts, but to avoid having parts on containers that might in the course of play be closed up with the player inside.
We can, if we wish, change the principles of what can be touched by writing new reaching inside or reaching outside rules. Returning to the example of the conical flask:
(Or this could equally be called "a reaching inside rule for the flask".) More generally, we could give the usual flexible description of what the rule applies to:
The "container in question" is the one to which the rule is being applied. Note that a reaching inside rule can "deny access" (stopping with failure), or "allow access" (stopping with success), or neither, in which case the decision is left up to any subsequent rules in the rulebook to make. If none of them decide, access is allowed.
If it seems possible that these rules will be employed by people other than the player, then we need to write them a little more carefully, and in particular we need to ensure that they print nothing for other people. In the first case below, anybody can reach through the glass; in the second case, only the player cannot reach into open containers.
The "person reaching" is, as its name suggests, the person trying to reach through the barrier in question.
Ordinarily, Inform has a simple model for visibility: it is either fully light or it is fully dark, and certain actions are impossible in the dark, such as examining something.
We first need to remember that darkness affects what actions are even tried, as far as the player's typed commands go. If the player is in a dark room, and there is a screwdriver on the floor, the command EXAMINE SCREWDRIVER will not try any action: the screwdriver is not "in scope", which means that the parser thinks the player does not have any means of knowing it exists. (The rules for scope can be modified – see the chapter on Activities.) But let's suppose that the player types EXAMINE BOOK, and is holding the book in question. The book is now "in scope", so the action "examining the book" is tried.
Some actions require light to be present, and "examining" is one of those. So Inform consults the visibility rules to see if it can go ahead. By default, there is only one visibility rule, which says "yes" in the light and "no" in darkness. Here, though, we create another one:
A visibility rule must always conclude "there is sufficient light", or "there is insufficient light", or else do nothing and leave it to other rules to decide.
It is a possibly unexpected fact that "looking" does not require light, but instead behaves differently in darkness – it prints a pseudo-room-description such as
instead of printing the description of the player's current room. This means that the "looking" action is unaffected by visibility rules. All the same, what "looking" does in the dark can be changed by using the two activities "printing the name of a dark room" and "printing the description of a dark room" (see the Activities chapter for details).
As we have seen, to describe an action fully takes a complicated little bundle of information – we need to know what is to be done, who will do it, and what it will be done to. There are times when we would like to remember an action and look back on it later (perhaps many turns later, after many other actions have taken effect) – but this is not easy to do with only the techniques we have seen so far. There are quite a few cases to get right, and it would be easy to not store quite enough of the details.
Fortunately, Inform provides a kind of value called "action" which can do all of this automatically. (In older versions of Inform this was called "stored action", but the word "stored" is now unnecessary, and makes no difference.) As with most other kinds of value, actions can be held in variables, "let" values, properties or table columns. For example:
creates a variable called "the best idea yet" which holds an action.
This will normally be created holding the default value – the player waiting. We really only have two ways to make more interesting actions. One is by typing them out explicitly, like so:
Here "pushing the button" is a constant of the kind "action", so it goes into happily into "best idea yet" in the same way that a number like 3 could go into a number that varies. The action must be specific in every respect, so "taking something" or "doing something" will not work – "taking something" is really a general description of many possible actions, not an action in its own right.
The other way to produce a useful action is:
This phrase produces the action currently being processed as a value – it literally stores the action, and remembers, if necessary, the exact wording of the player's command at the time it was stored – so that even actions arising from commands like LOOK UP X100 IN THE CODE BOOK can be stored faithfully. Examples:
This only makes sense if an action is currently going on, so it shouldn't be used in "every turn" rules, for instance.
So much for making actions: now for making use of them. The first obvious idea is to store up an action for several turns and then have it take effect later. That's easily done: just as we can "try" any action written out explicitly, so we can also try a stored one. The phrase to do this has exactly the same wording either way, since it does the same thing either way.
But actions can still be useful even if we never intend to try them. For one thing, we can say them, and this produces a fairly natural description of what the action is:
will produce text such as:
One of Inform's most convenient features is its ability to test if the action being processed matches vague or complicated descriptions of whole classes of actions. For example,
works even though "taking something" is not a single action; it's a description which could apply to many different actions (taking a box, taking a ball, and so on). What Inform tests is whether the "best idea yet" value, a single action, fits this description or not. We can be even vaguer:
Just occasionally, this can lead to ambiguities. For instance,
fails because Inform thinks "wearing" is meant in the sense of the current action having clothes on, so it produces a problem message. To avoid this, simply write:
which can't be misunderstood. Something else to be aware of is that the terms "actor", "noun" and so on will refer to that action: for instance, in
"noun" here refers to the noun in "best idea yet", not to its meaning outside of this phrase (if indeed it has such a meaning).
When dealing with actions, we sometimes want to know what they are dealing with. We can extract this information using the following phrases:
This phrase produces the action name part of an action. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then
This phrase produces the (first) noun of an action. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then
If the noun is something other than an object, this produces just "nothing", the non-object.
This phrase produces the second noun of an action. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then
If the second noun is something other than an object (for instance for the command SET DIAL TO 3417 it would be the number 3417), this produces just "nothing", the non-object.
This phrase produces the person who would be carrying out the action if it were being tried. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then
The following phrase is a convenient shorthand form:
This condition is true if the object appears as any of the actor, the noun or the second noun in the action. Example:
would be true for "give revolver to Algy", "Algy trying flying the Sopwith Camel", "examine Algy" and so on, but false for "ask Raymond about secret airfield".
This phrase is now seldom needed. It produces a literally typed action as a value. Example:
Nowadays in most contexts we can just type "pushing the button" as a value, and that will work fine, so this phrase is retained only to keep old code working.
Looking at the action-processing diagram, there seem to be a bewildering number of ways to intervene. For instance, suppose it must be fatal to pick up a land mine. All six of the following rules would do the business:
So which should we use? Of course, we could decide that it really doesn't matter: what works, works. But it is a good idea to play along with the conventions used by Inform, if only because that will make our rules interact better with each other and with rules by other people which we may someday want to borrow. So this chapter ends by offering a few guidelines. Let us suppose that we have some effect which we want to achieve.
1. Are we just trying to correct the player's typing?
For instance, responding to the command "STEAL GOLDEN EAGLE" with a reply like "To steal something, just try to TAKE it." It is bad style to make a special action for this, which does nothing except to print up this text: better is to use the "Understand … as a mistake" technique, which will come up in the chapter on Understanding.
2. Does the effect apply only to a particular situation, or is it a general phenomenon?
In other words, does the effect apply only to particular people, things or places, or is it a generic rule of play? In the case of the land mine, this is an easy question to answer: it is a unique situation. On the other hand, stopping the player from carrying unduly heavy weights would be a generic rule of play.
Rules like the one saying that photography is only possible if one holds the camera are, by convention, also counted as generic rules of play: they are not really special rules about the camera, but apply to all possible acts of photography anywhere, so are actually generic.
Sometimes we can choose our own answer to this question, and go either way. Suppose we want a certain place to be muddy-floored, affecting things that happen there. One way would be to write exceptional rules applying to that one room. But we could alternatively create a general concept of muddiness ("A room can be clean or muddy. A room is usually clean.") and then regard the new behaviour as being a set of generic rules applying in muddy rooms. We could then, of course, create a second muddy room with much greater ease, or transplant these rules to other works and have muddy rooms in those too.
3. Particular situations: use Instead or After (or sometimes Before).
The next question is: does the effect kick in after the hoped-for action has taken place, or not? In the case of the land mine, to answer that means deciding whether we think the detonator is sensitive to the slightest touch – in which case the explosion would happen at the first touch, and should be in an "Instead" rule – or whether one must actually pick up and disturb the mine – in which case an "After" should be used.
That leaves us a choice of two rulebooks if the effect takes place when the merest impulse towards the action is felt: "Before" and "Instead". Which to use? In cases of doubt, choose "Instead". But if the effect is intended to absolutely suppress all such impulses – for instance, in a silent examination room there must be no talking – then "Before" might be more appropriate. We could imagine that someone about to say something first has a mental impulse to speak, then opens his mouth so that it becomes visible to others that some talking is about to go on, and finally utters words. Here are three possible responses:
4. Generic situations: work with action rules (or sometimes Before).
(a) If the effect takes place only when an action is definitely being tried, then we should use one of the action's three rulebooks: check, carry out or report. Check rules should do nothing, and should say nothing either unless they block the action (in which case, they should say why).
Carry out rules must not block the action – it is too late for that – and should not say anything – that hasn't happened yet. (There are a few exceptions: if the action is to look at something, then carrying it out is in a sense the same thing as reporting it. But in all cases of doubt, a carry out rule should say nothing.) Adding a carry out rule to an existing action can make it do something extra.
Report rules must neither block the action nor do anything. Working with new report rules is a way to make more natural-seeming, or more informative, messages appear. For instance, an effect where we want to be able to see through a door when it is first opened ("You open the panelled door, through which is the Board Room.") would be a case for a report rule.
In all cases, it is good style to write check, carry out or report rules in such a way that they could be used in other works too, or in situations that could conceivably have happened in this one (even if in fact it never does). We may one day want to put our new rules into an extension to be used by other people or in other projects, after all.
In this chapter, we have only seen the addition of new rules. We could add a new "check taking" rule, for instance, with the techniques seen so far. But what if the effect we want is not a matter of adding a rule but taking away, or restricting the applicability, of an existing one? In that case, we will need to say that the rule "does nothing" under certain circumstances (see the Rulebooks chapter). The check, carry out and report rules for all of the built-in actions are named, and they appear in the Actions index.
(b) If the effect takes place to divert or supplement an action, before that action actually takes place, then this should be done with a "Before" rule. This is the biggest practical use of "Before" rules: to try other actions, either instead or as well as the one just getting under way.
For example, if we want an automatic mechanism to try opening a container before taking something inside it, that would be a classic case for "Before". Indeed, that is the only way it could work – "Before" rules have a chance to get in before the touchability conditions are tested.
If we wanted a special "stealing" action for the act of taking another person's possessions, we might want to divert any taking action for such items into our new "stealing" action – that too would be a "Before". This would ensure that any "Instead" rules to do with taking do not apply.
5. Changing the behaviour of out-of-world actions.
Remember that "Instead", "Before" and "After" do not apply: so use "check" rules to forbid certain out-of-world activities, or specify that their rules do nothing (see the Rulebooks chapter).
Finally…
These are only guidelines. The system is designed to be flexible in order to give the author the widest possible range of options, and nobody should feel ashamed of making use of them.
Descriptions of things – "open door", "people in the Drawing Room" – have already had a whole chapter to themselves. But descriptions are only half of the story of Inform's highly flexible language for talking about places, things and circumstances: this chapter is the other half, and is about the "sentence". Of course all text is made up of sentences, but Inform has a more specific meaning than that. Consider the following pieces of source text:
What these three extracts have in common is the sentence "the mouse is in the teapot". Such a sentence can be used in three different ways: to declare the original state of the world, to ask during play if the world currently has that state, or to change things during play so that it does.
Actually, though, only definite sentences about the present can be used in all three ways. A vague instruction like
will fail, because there are so many ways in which Darcy might be able to see the mouse that Inform has no way to know how to arrange matters. And this by contrast is not merely difficult but impossible:
Which cannot be arranged because the past cannot be changed.
Verbs also turn up inside the more complicated descriptions. For instance,
are both descriptions, not sentences, but they contain "to be" and "to be able to see" respectively.
This chapter is about the verbs which can be used in sentences and descriptions. Inform involves many other features which use verbs – the action "taking the mouse" and the phrase "end the story" both use forms of verbs (to take and to end) – but this chapter has nothing to do with them: so for the sake of clarity, we will call verbs that occur in sentences "sentence verbs".
A sentence consists of two nouns with a verb between them. Usually, the two nouns are descriptions, as in:
Here "Mr Collins" and "a lighted room" are descriptions. But there are sentences where one or both of the nouns is a value of some other kind. For instance, in
the sentence "the score is greater than 10" consists of two number values ("the score" and "10") connected by a verb part ("is greater than").
This chapter is about getting the most out of sentences by defining new verbs to express ideas not already built in to Inform. Before we can define a new sentence verb, however, we must first look at the meanings of verbs: which Inform calls "relations".
Relations are what sentences express. They are yes/no questions about pairs of things: for example, to say that the coin is in the purse is to say that a particular relation ("being in") is true about a specific pair of things (the coin, the purse). It is neither a fact about the coin nor about the purse, but about the two together.
Inform comes with a number of relations built in, almost all of which have been used in previous chapters already. The following table names some of the more useful ones, giving examples of sentences to bring them about:
These relation names do not trip off the tongue, but they relatively seldom need to be referred to.
The same meaning can often be expressed by using several different verbs, or using the same verb in several different ways, as in the following examples:
all of which boil down to saying that the coin and purse satisfy the containment relation. Because of that, relations are not the same as verbs. To create a new idea, we will need first to create a new relation, and only then can we set up a verb which allows us to talk about that relation.
Inform has altogether five mutually exclusive ways in which one thing can be physically joined to another one:
This is why we cannot have
simultaneously, and it is a rare exception to the general rule that having one relation does not affect having another.
But there is also a sixth relation used in Inform for these meanings: the possession relation, which is the meaning of the verb "to have". At first sight this looks the same as the carrying relation, but in fact it is a convenient shorthand for "carrying or wearing", provided for conditions rather than assertions:
will be true during play if he is either carrying or wearing the shirt.
Still another relation exists which can be tested, but not declared to be true or false: the concealment relation, which is the meaning of the verb "to conceal". So we can ask:
We can create new relations like so:
Every relation has a name which ends with the word "relation", and in this case the name is "loving relation". While the name is often just two words long, as here, it doesn't have to be:
makes the "adept sensitivity relation". (The limit is 32 words.)
In such a definition, we have to say what kind of thing appears on the left and right of any relation, and also whether "one" or "various" possibilities can exist. In the example
what we are saying is that only people love; that they only love people; and that each person loves only one other person (at any given moment).
The "various" part comes in because, for instance, we might have:
so that various people (Verenka and Liubov, to name but two) love one person (Stankevich). But we are forbidding anyone to love two other people at the same time: Stankevich must decide which of them to love, or pick someone else, or no-one at all. Similarly, we would not allow
It is sometimes convenient to give a name to the other side of a relationship, so to speak. We might imagine:
It would then make sense to talk about "the owner of Loulou", and we could have phrases like "now Flaubert is the owner of Loulou" or "if the owner of Loulou is a woman…" and so forth. This, however, would not be allowed:
because "the pet of Flaubert" would be ambiguous: he might have owned dozens.
The relationships described in this chapter so far are by no means always reciprocated. For instance, if a stone is on a table, then it is never true that the table is also on the stone. And the question may not even be meaningful to ask. If Peter wears a jacket, the jacket does not even have the possibility of wearing Peter.
But sometimes we do want a relation which works both ways equally well. These are simple to set up:
The effect is that various people know various other people, and this is always reciprocated. If Daisy knows Sophie then, automatically, Sophie knows Daisy. This even-handedness is maintained throughout play, so that whatever changes are made it is always true that if A knows B then B knows A.
And similarly for a reciprocal relation between one and another:
In this case, we can again give a name to the partner under a relation:
and now, for instance, we may have that the spouse of John is Yoko and the spouse of Yoko is John.
Since many of these examples have involved people, it might be worth mentioning again that any kind can be involved, not just the "person" kind.
Finally, there is a kind of relation which binds even more strongly.
This is a kind of relation which divides people up: we might wish to have all the Icelandic people related to each other, all the Peruvians to each other, and so on. If there were a Pacific island called Informia with one inhabitant, then that person would be related only to himself. As time goes by, we could imagine people emigrating, and so on, so that these groupings would switch: perhaps everyone would leave Belgium and, for a while, there would be no Belgian nationals at all.
The testing command RELATIONS prints out the current state of all the relations created in the source code. For instance:
That can produce a lot of output. To see only a single relation, or to see it at some intermediate point in a calculation, there's also a testing phrase:
This phrase is for testing purposes only. It shows the current state of the named relation, that is, it shows which values relate to which other ones, where it's possible to do this in any sensible way.
But this is a phrase – not a typed command.
It is all very well to define new relations, but this does nothing if there is no way to assert that they are true, or to ask whether they are true or false. That requires a verb: in fact, a relation is nothing more than what Inform uses as the "meaning" of a verb. The assertion verbs built in to Inform have the following built-in relations as their meanings:
Two of Inform's built-in relations are expressed using prepositions instead:
It would be easy to make verbs for these if we wanted ("to adjoin", say) using the techniques of the next section.
The verb to be is grammatically different from any other, and its meaning is too complicated to be fully expressed by any one relation. A great deal of the Inform program is given over to its "meaning", which we are not allowed to change or imitate. The "equality relation" is simple enough, and is the one implied by conditions like
but to be can have more complicated implications – "if Mr Wickham is hungry" clearly doesn't test whether two quantities are equal. Fortunately the other verbs are much simpler.
There are a few other built-in verbs, as can be seen in the Index, but these are mostly for experts only. For example:
"To mean" can be used to make new verbs, as we'll soon see. Provision is to do with whether something can have a given property: for example, "if R provides the property lighted" tests whether R is able to have this property, not whether it actually has it at the moment.
Here is an example definition of a new verb:
Once this is done, we can write the assertion
which will do the the same thing as
because both verbs have the same relation as their meaning.
Earlier versions of Inform needed to be told how to make other parts of the verb, but that's rarely true now. Just writing:
is enough for Inform to understand "he sports", "they sport", "he sported", "it is sported", "he is sporting", "he had sported" and so on. It works with irregular verbs, too; it has a very comprehensive dictionary. But it's legal to spell out the conjugation if need be:
Occasionally it's convenient to have the relation the other way around. For instance:
With that defined, these two sentences have identical meanings:
Reversed in this sense means that the things related – the subject and object of the verb – are the other way round.
The Phrasebook index contains all the verbs associated with assertions, in the Verbs section. When we add new verbs to our source, those will appear in the Phrasebook as well.
The verbs above ("to grace", "to sport") are short ones, but we're free to make them longer than that. For example:
Here we have "to cover oneself with", four words long; the limit is 29.
The term preposition is used here, a little loosely, to mean anything which we add to the verb to be in order to talk about some relation or other. We have seen many examples already, such as:
These are defined just the way verbs are. Compare the following:
The result of this is that
are exactly equivalent, and so are these two descriptions:
While most prepositions are short ("in", "part of", "suspicious of"), they're free to be longer if need be ("inordinately far away from"): the limit is 30 words, which should be ample.
We can also define verbs as auxiliaries, like so:
Now we can ask if Poirot "can approach" Hotchkiss, and so on.
We have already seen, in the chapter on Descriptions which is a forerunner of this one, that Inform provides not only "adjacent" as a way of seeing if one room is directly connected to another, but also "the best route from A to B", which allows us to see if any sequence of moves connects them.
Something similar – in fact, simpler – is allowed for any relation between objects. Suppose we would like to go sledging: we can go downhill, but not up. Some quite distant places may be reachable, while others close by may not be, even if lower than us, because they would involve climbing again at some point. The following would implement this:
Here we're making use of:
This phrase tries to find a shortest route between the two given endpoints, using the given relation of objects to determine single steps. Example:
The result is the special object value "nothing" if the two endpoints are the same or if no route exists.
This phrase tries to find the length of a shortest route between the two given endpoints, using the given relation of objects to determine single steps. Example:
The result is 0 if the two endpoints are the same, or -1 if no route exists.
Another example would be the "six degrees of separation" game, where it is claimed that any two people on Earth are connected by a sequence of up to six acquaintances. In an Inform implementation, we might talk about "the next step via the friendship relation from George Bush to Saddam Hussein", for instance, a phrase likely to evaluate to Donald Rumsfeld, and then
would be… but that would be telling.
As with route-finding through the map, finding "the next step via" a relation can be slow. For instance, suppose we have dozens of articles of clothing all partially revealing each other, connected by two relations – overlying and underlying. Then "the next step via" these relations allows us to establish what can be worn on top of what else. If we need to calculate this often, and there are enormous wardrobes of clothes to choose from, speed starts to matter.
Once again there is a choice of algorithms: "fast" and "slow", where "fast" needs much more memory. To make route-finding for a given relation "fast", we have to declare it that way:
Otherwise, the "slow" method will be used.
This "with fast route-finding" note can only be added to various-to-various relations. (Although route-finding through various-to-one and one-to-various relations is fully supported, it exploits the relative simplicity of these problems to use a more efficient algorithm than either "fast" or "slow".)
Adjacent rooms and routes through the map for route-finding through the map rather than a relation.
One last way to create a new relation and, in many ways, the easiest of all. If we write:
then we would be able to talk about a handle being joined to a door, and a door being joined to a handle, and so on. We are not allowed to declare:
because the question of whether they are joined is not for us to decide: that will be for the condition to determine, whenever we test it. Similarly, we cannot meaningfully write
(and Inform will not let us) because this relation is not something we can force either way: we can make it come true by other means, maybe, but we cannot simply make it true by saying so. Lastly, this kind of relation is restricted in that we are not allowed to find paths or calculate numbers of steps through it.
So this way to define relations is, on the face of it, just a sort of verbal trick to write conditions in a more attractive way. The more flexible, changeable relations in previous sections have much greater expressive power. All the same, it is nice to be able to write -
and then to be able to write rules like:
As with other relations, there's no reason why we have to use objects. For example:
which enables us to write:
And here is a mathematical one:
We now find that "2 divides 12", "5 is not a factor of 12" and "12 is divisible by 3" are all true. Again, we are only really gaining a nice form of words, but improving the clarity of the source text is never a bad thing.
Although most of the examples in this chapter have involved objects, relations can connect almost any values together. We can create relations in groups, one to various relations, various to one relations, one to one relations, and various to various relations for any combination of kinds. For example:
How might we make use of this? Clearly it would be impractical to keep trying:
to find out what "caviar" belongs with. It's still harder to find out if it belongs with anything at all -- in theory we would have to try every possibility, which of course is impossible. Instead we have these phrases:
This condition is true if the value V is such that V relates to something by the given relation. Example: suppose partnership relates various texts to various texts. Then we can test
This condition is true if the value V is such that something relates to V by the given relation. Example: suppose partnership relates various texts to various texts. Then we can test
If a partner does exist, then we can find it with:
This phrase produces an Y such that the given value V relates to Y by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain
which might be, say, "cheese". It's a run-time problem to use this if no such Y exists.
This phrase produces an X such that X relates to the given value V by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain
which might be, say, "chalk". It's a run-time problem to use this if no such X exists.
Of course, there might be many answers to this question, so perhaps these are neater:
This phrase produces a list of all the X such that X relates to the given value V by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain
which might be, say, { "chalk", "grapes", "macaroni" }. The answer might be the empty set, but that's not a problem.
This phrase produces a list of all Y such that the given value V relates to Y by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain
which might be, say, { "cheese", "blackboard", "cliffs" }. The answer might be the empty set, but that's not a problem.
Finally, it's sometimes useful to get at the list of all values which can appear on the left or right hand side of a relation. We need tongue-twister like wording to do it, but:
This phrase produces a list of all X which relate to anything under the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain
This phrase produces a list of all Y which anything relates to under the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain
For efficiency reasons, there are no guarantees about what order these lists have – but they can of course always be sorted when found.
As we've seen, most relations have names – "containment relation", for instance. These are themselves values in Inform, though there are a few restrictions on how they are used. (Relations can contain a colossal amount of data, so we don't want to have to copy them casually.)
Consider these two examples:
Here "parity relation" and "joint magnitude relation" are both values of the same kind: "relation of numbers to numbers". In general, every relation is a value of kind "relation of K to L", for the appropriate kinds K and L. So the parity relation doesn't have the same kind as the containment relation, for example. Because it often happens that K and L are the same, we can just say "relation of K" in this case, so we could equally say that the kind of the parity relation is "relation of numbers".
This is useful to know when writing phrases like so:
and now "chart parity relation" will work nicely, but "chart visibility relation" will be rejected (as it should be, because it relates things, not numbers). In general, if R is any relation, we can write
to test, set and unset a relation R between two values. (Inform checks that the values X and Y have the right kind and produces a problem message if not.)
Several useful adjectives can be applied to relations:
So for example it's possible to ask
With some relations, it's possible to clear them out by writing:
and with temporary relations (see the next section), it's even possible to change their valencies (one-to-one vs. one-to-various, etc.) using "now", but only when they are empty. The exceptions where "empty" can't be used are those which can't be changed at all, like the parity relation above, and a few built-in cases such as the support, containment and incorporation relations, where emptying would dissolve the model world in a disastrous way.
So far in this chapter, we've only seen relations which exist permanently during play. The relationships might change – sometimes Red Riding Hood would be in the Woodcutter's Cottage, sometimes not – but the relations themselves were eternal.
In fact, though, we can also create relations to be dynamic data structures, like lists:
This phrase creates a new temporary variable, and sets its value to the identity of a newly created and equally temporary relation. These last only for the present block of phrases, which certainly means that they exist only in the current rule. Example:
This makes a purely temporary various-to-various relation between texts, which lasts as long as the temporary value "password dictionary" lasts. By default, relations are various-to-various, but we could instead write, say:
Such a relation exists only in the current phrase, and is destroyed when the phrase finishes, like any other "let". Of course there's no verb whose meaning is this relation, but that's no obstacle, because we can manipulate it using "relates":
(At present such a relation cannot be used outside its own phrase.)
It is easy to say what verbs are for: they are to express relations. But what are relations for?
Inform 7's focus on relations between objects is unusual as an approach to interactive fiction; the concept does not exist in most design systems, or rather, it does but is submerged. Traditional design systems do, after all, have the spatial relations of being inside, on top of, and so on. It could well be said that these are the only relationships that inanimate objects ever have. A stone can be on top of a table, and if so then that expresses their entire association.
This is because the stone, and the table, have no opinions, emotions, knowledge or memory. If the stone is taken away and then put back, nothing has changed. People, on the other hand, tend to remember having met each other before; they like being in some places, but not others; their behaviour depends on who, or what, is nearby. Being conscious, they have internal states, unlike the stone. Relations are a simple but powerful way to express and talk about such connections, and although they have numerous uses in physical contexts too, they are at their most powerful when helping to make the characters of interactive fiction come alive.
A conspicuous difference between interactive fiction and a traditional novel is the point of view from which it's told. Inform usually produces text like:
where a novel would usually write:
Standard interactive fiction (IF) is second person singular, and present tense; most novels are told in the third person singular, and past tense.
But these are just conventions – a few novels, for example, use the so-called present historic ("Napoleon looks up at the sky and sighs. Must Ney always be so doubting?"), and plenty are told in the first person singular ("I always get the shakes before a drop."). Inform allows some of this flexibility, too. The two values:
control the style of the text produced. The story viewpoint has to be one of the values:
(which are actually the six possible values of a kind called "narrative viewpoint"), while the story tense must be one of:
(from a kind called "grammatical tense"). Combining these gives 30 possibilities in all, though only a few are at all commonly used.
It's important to make a very large caveat here: Inform uses these settings in producing the replies ("responses") by the built-in actions, but the only way for all of our own text to have a particular tense or narrative viewpoint is to write it that way. If we write:
then we're likely to see the following peculiar transcript:
That's because the response ("We couldn't go that way") was constructed to follow the settings for viewpoint and tense, but the fixed text of the room description wasn't. In fact there are ways to write the room description so that it would adapt itself automatically, as we'll see, but it takes a fair amount of work. More simply:
In short, tense and viewpoint switching is neat, but it isn't magic.
If we want to write text which will work in whatever the current tense is, the following turn out to be useful little conveniences:
Produces "here" if the story tense is the present tense, and "there" otherwise.
Produces "now" if the story tense is the present tense, and "then" otherwise.
Paying attention to the tense and viewpoint is one reason why text might need to adapt. Another is that it might need to adapt according to whether nouns are singular or plural, or whether it talks about the player or some third party. For example, the following rule isn't ideal:
Most of the time it's fine ("The V-ray is pinned down by Dr Zarkov's force field"), but then:
Which is a little unfortunate. But the correction is very easy:
The result is much better: "The V-ray is pinned down…"; "You are…"; "The condensers are…". In fact, it's also convenient because it adapts to the story viewpoint and story tense: "The condensers will be pinned down…"; "He was pinned down…".
How does Inform do this? The answer is not that "[are]" is a specially-written text substitution. In fact Inform can do this with any verb that it has a definition of. For example,
would also adapt itself – "The V-ray carries too much static charge", and so on. There aren't many verbs built in to Inform, but "[have]" and "[carry]" and "[wear]" and "[can]" may be useful, and "[can see]" and "[can touch]". Negative forms like "[are not]" are also available:
might produce "The V-ray will not be able to touch the ionizer terminal.", for example.
As these examples hint, the verb adapts itself to the most recently printed object name. All of this only works if the previous object's name is printed from a substitution. So:
will work -- correctly forming "The condensers are working.", "The condensers will be working." or "The condensers were working.", according to the story tense -- but
probably won't work. Inform doesn't have any way to understand the raw text outside of the text substitution marks "[" and "]", and it doesn't recognise "The condensers" as being something's name.
Something else to be careful with is the use of lists. If we write this:
then Inform is likely to print:
because it looks at the most recently named object – the V-ray, singular – to decide whether to use "is" or "are". On the other hand, Inform gets this right:
Because Inform constructs the list itself, it's able to appreciate that the things listed are jointly the subject of the verb, and it uses that information to decide on "is" or "are". So:
If we need an adaptive message with a verb which doesn't belong to Inform's built-in set, all we need do is define it. In the previous chapter we defined verbs by giving them meanings, but in fact that's optional. For example:
defines a verb without telling Inform what it means. Inform will throw a Problem message if we try to write text like:
because, after all, it doesn't know what "retrofit" means. But it does still know how to print it, so this works:
which might come out as "Dale retrofits the Mecha-Mole", or "Barin's archers retrofitted the Mecha-Mole", and so on.
This is especially neat for writing a single response to an action which works regardless of who the actor was. For example, the Standard Rules include:
And this can make either:
In second-person-singular IF, the player is always "you". Many messages look like so:
where the subject, or the object, of the sentence is "you". But what if we want to have this text adapt itself to different narrative viewpoints?
The solution is to use the following:
The capitalised and uncapitalised versions are identical except, of course, that the initial letter of the resulting text is upper case in one but not the other. As examples of these:
Notice that all five of these forms are differently worded, in English. That's the reason why we use the plural to write them – the traditional second person plural forms would be "you", "you", "your", "yours" and "yourself", so we wouldn't know if "[you]" was supposed to be the subject or the object of the verb. So the convention with all of these adaptive forms is that we use "we" and its variations. (That's also why the verbs are written in the plural – "[carry]", not "[carries]".)
The family in the previous section – "[we]", "[us]", "[our]", "[ours]", "[ourselves]" – always referred to the player. But we also sometimes want to refer to other things without naming them. For example, how should we adapt this?
We can easily make the verb adapt – change the "has" to "[have]" – but the trick here is to make the "It" adapt to cases where what's examined is plural, or animate. What we want is:
For example, this produces:
Note that we have to say "[regarding the noun]", not just start in with "[They]", because nothing has been named so far in the sentence – so Inform doesn't know what object it refers to. "[regarding the noun]" prints nothing, and simply tells the printing part of Inform that the subject has changed.
This isn't always needed:
works fine, because printing "[the noun]" changes the subject to that, and then "[they]" agrees with it automatically. The text might come out, for example, as:
We have a family of five text substitutions here, matching those in the previous section:
There's also the peculiar impersonal non-object for English sentences like "It is raining" or "There are books":
These look pointless – but consider the two texts
The first one risks printing "We took the scissors. It rain harder.", because it makes "[rain]" agree with "scissors", which are plural. But the second text makes "[rain]" agree with "[it]". And, as a convenience:
do the obvious thing using the current story tense.
Finally, we occasionally want to agree with a number:
Consider the following message: how might we make this adaptive?
The verbal part is easy enough, but "that" needs a new feature.
This could then adapt to, say,
Notice that it's "[regarding the noun][those]", not just "[those]". If we wrote "[those]", Inform would make it agree with the player, who was printed earlier in the sentence by the "[We]".
Lastly, how about:
This time we want:
which might adapt to, say,
Actually, "[regarding …]" can be used for a description of possibly many items, too. For example:
Every turn when the player carries something:
So if the player carries just a single coin, say, this automatically becomes:
but if the player carries a pair of scissors (a single plural-named item) or a coin and an iPhone, it becomes:
Once again these text substitutions are available in capitalised and uncapitalised forms:
In fact "[Those]" and "[those]" do subtly different things, besides the capital letter, because "[Those]" expects to be the subject of the sentence and "[those]" the object, and this makes a difference if the noun in question is a person. If the noun is an odious person called Tilly then
would come out as "She is unacceptable" – so "[Those]" becomes "She" – but "You've never liked her" – so "[those]" becomes "her". If we need these in different cases, we can explicitly ask for that:
English uses so-called "modal verbs" to change a sentence so that it talks about something only possibly happening. For example, the sentence "Fred goes to school" can be modified to "Fred must go to school", "Fred should go to school" or even "Fred might go to school".
Inform supports the use of modal verbs in text substitutions. For example,
would in the present tense come out as "Fred might go to school.", but could alternatively be "Fred might have gone to school." As this example shows, all that's needed is to take a verb we'll call V – this case, "go" – and we can write any of these:
That helps us to handle informal usages like this one:
To make this message adaptive, we write:
which can adapt in surprising ways -- "They won't be able to go that way.", for example.
Note that the verb V has to be one that Inform knows. But that's easy:
and then
could produce "Fred might not have discombobulated so easily", for example.
Contractions usually take the form of part of a word being missed out and replaced by an apostrophe. We've already seen "[can't]", "[couldn't]", "[mayn't]", "[mightn't]", "[mustn't]", "[shouldn't]" and "[wouldn't]", for example. But Inform supports other contractions, too, as follows.
The English verbs "to be" and "to have" are unique in having contracted forms, which we can write "['re]" and "['ve]", like this:
which might produce, say, "I've got rhythm. I'm cool.", or "He'll have rhythm. He'll be cool.", or "You had got rhythm. You were cool." (The contractions don't appear in the past tense; but the spacing fixes itself automatically.)
The Standard Rules often use a special text substitution for responses like this one:
This is exactly like "[Those]['re] hardly portable" except that if the plural is needed, Inform prints "They're hardly portable" rather than the correct, but not quite idiomatic, "Those're hardly portable". (If we wrote "[They]['re] …", that would get the plural form right, but then the singular would be "It's hardly portable" not "That's hardly portable".)
Only a few English verbs have contracted negative forms, beyond those already mentioned. Inform knows these informal forms:
For example,
can produce variations like these:
Each verb known to Inform is actually a value of the kind "verb". To refer to a verb as a value, we have to put the word "verb" in front, as in these examples:
all of which appear in the Standard Rules.
Two adjectives are provided for use with verbs: "modal" (or "non-modal") to pick out verbs like might, could, should, and so on; and "meaningful" (or "meaningless") to pick out verbs which have a defined meaning as an Inform relation. For example, in the Standard Rules, the verb contain is meaningful, the verb might is modal, and the verb provoke is meaningless.
If V has a meaning as a relation of objects, then "meaning of V" produces that relation. For example,
produces:
As this demonstrates, if a verb has no meaning, or its meaning doesn't relate to objects, we get just the equality relation.
In fact, Inform even defines a verb "to mean": it's meaningful, and its meaning is the meaning relation. Thus:
is true. More usefully, we can search our vocabulary like this:
which, unless any non-Standard Rules definitions have been added, produces:
Note that the meaning relation can't be changed at run-time: it is not clear what it would even mean to do something like -
with the story already started, so this will produce a problem message.
Adapts the given verb to the current story tense and story viewpoint. For example, "you [adapt the verb provoke]" might produce "you provoke".
Adapts the given verb to the current story tense but the given viewpoint. For example, "he [adapt the verb provoke from the third person singular]" might produce "he provokes".
Adapts the given verb to the given tense but the current story viewpoint. For example, "you [adapt the verb provoke in the past tense]" might produce "you provoked".
Adapts the given verb to the given tense and viewpoint. For example, "we [adapt the verb provoke in the future tense from the first person plural]" might produce "we will provoke".
Adapts the given verb to the current story tense and story viewpoint, giving it a negative sense. For example, "you [negate the verb provoke]" might produce "you do not provoke".
Adapts the given verb to the current story tense but the given viewpoint, giving it a negative sense. For example, "he [negate the verb provoke from the third person singular]" might produce "he does not provoke".
Adapts the given verb to the given tense but the current story viewpoint, giving it a negative sense. For example, "you [negate the verb provoke in the past tense]" might produce "you did not provoke".
Adapts the given verb to the given tense and viewpoint, giving it a negative sense. For example, "we [negate the verb provoke in the future tense from the first person plural]" might produce "we will not provoke".
Note that the verb doesn't have to be named explicitly for use by the adapt or negate phrases, so for example:
produces:
Lastly, we can get at three other useful parts of a verb, too. These aren't adaptive, of course: a verb only has one infinitive form.
Produces the infinitive of the given verb. Note that this is without a "to": for example, "[infinitive of the verb carry]" is "carry", not "to carry".
Produces the past participle of the given verb. For example, "[past participle of the verb carry]" is "carried". Warning: because modal verbs like "should" or "might" are defective in English, this will produce odd results on them – "shoulded" and "mighted", for example.
Produces the present participle of the given verb. For example, "[present participle of the verb carry]" is "carrying". Warning: because modal verbs like "should" or "might" are defective in English, this will produce odd results on them – "shoulding" and "mighting", for example.
Most of the text which the player sees is drawn from the source, but mixed in with this are messages apparently added by Inform itself – usually in the form of short sentences saying that something has been done, or that something can't be done. Such pieces of text are called "responses", because they are almost always replies to commands. For example:
Responses like this, which don't appear anywhere in the source text, come from one of the extensions being used; most often from the Standard Rules, the "extension" which is automatically included in every project. The SR contain many small rules, and almost all of these are capable of producing one or two standard responses. These are labelled with the rule's name and then a bracketed letter – (A), (B), (C), … as needed so that every response has its own unique name. There's nothing very mysterious about how this is done. For example, here is a rule with one response:
which makes the familiar text "You are carrying nothing." a response named:
These names are actually values, belonging to the kind "response". Because of that, if we try this:
Inform will produce
since we gave Inform a value to print, and that's just what it then did. As an alternative:
This text substitution writes out the current text of the given response.
Thus,
produces
These responses are named so that they can be changed. Most IF authors dislike one or two of the existing responses, and some would like to change almost all of them to give the text a different style; and extensions for IF in languages other than English change literally every response, of course.
It's very easy to change responses:
and we can even do this dynamically during play:
just as if we were setting a variable.
In practice we can't change these responses unless we know what they're called. One way to find out is just to read through the extensions we're using, but that's a laborious process. A more practical answer is to type:
which replies by listing the sets of responses currently available; for example, it says that RESPONSES 1 is the set of responses for the Standard Rules. We can then type exactly that:
and so on. This lists all of the responses, rule by rule, along with their current texts.
In a poem, or in a novel, exact scientific measurements are not the point. So a writer who wants to set up ways to describe the sky at different times might go for something like this:
And nobody is interested in the sun angle, the percentage of cloud cover, or any of the other numbers behind all of this. Similarly, if we walk into a familiar office which has been disturbed, we might well say "Look! The filing cabinet is in the middle of the floor." We are not likely to exclaim "Look! The filing cabinet is 1.2m from the east wall and 2.1m from the north wall."
But some writers of interactive fiction do like to make use of physical realism. For instance, it's easier to forbid a bulky object being taken through a narrow doorway if there is a way to measure and compare sizes.
Most computer programs write numbers in the same way, whatever they're used for. But human beings don't. If someone says "How far is Duluth?", we're more likely to say "100 miles" than just "100". This is a useful feature of natural language, because it means we always know how to translate that number into reality – it's 100 miles, not 100 km, or 100 inches; and it's definitely a distance, not 100 apples or 100 kilograms.
Inform lets us use plain numbers if we want to, but it also allows us to create numerical kinds of value:
That kind of definition, and the consequences, will be the subject of this chapter. But we will first look a little harder at the two numerical kinds of value we get for free: "number" and "real number".
Inform uses two different kinds of numerical quantity: "number" and "real number". Neither is better than the other: they're different approaches, each good for a different purpose.
What Inform calls a "number" is a whole number, positive, negative or zero. The range of numbers we can hold is not unlimited – if the format Setting for a project is the Z-machine, then we have:
and if it is set to Glulx, then we have:
Numbers from zero to twelve may be written out, but larger ones must be written as numerals. So "twelve" or "12", but "13" only.
If we're using Glulx, Inform also has "real numbers" such as
which are not restricted to whole numbers, but which are stored only approximately: only about six to nine decimal digits can be relied on. For example,
produces
because these two numbers are so close together that Inform can't tell them apart. But we do also get the ability to represent enormously large or small quantities, and to help with that, Inform can read and write "scientific notation". For example,
is equivalent to typing
The "x 10^23" part tells Inform that the decimal point belongs 23 places to the left of where it's written. (In scientific papers, the 23 would be printed as a superscript -- it's 10 to the power 23 -- but that's not convenient to type in to the source text, so we use the "^" symbol to indicate superscript.) The range we can hold is roughly:
It's hard to convey just how enormously different these two numbers are: if we used them to measure widths in meters, one would be a hundred trillion trillion times smaller than an atom, the other a billion times larger than the entire visible universe. Scientific notation is the ultimate adjustable spanner.
Inform also allows the two most famous real numbers in mathematics to be given by their names:
which are close to 3.14159265 and 2.7182818 respectively. (Lower case letters must be used: these can't be written "Pi" or "E". Euler's constant gamma, always in the bronze medal position, will have to be written out longhand as 0.5772156649.)
Most computer programming languages traditionally write floating-point numbers using the E notation, like so:
Inform will follow suit if the use option "Use engineering notation." is set, but by default it isn't.
This section notes down some technicalities about real numbers which need to be put down in writing somewhere, but won't affect most people most of the time.
Inform allows us to use numbers whenever real numbers are expected, and converts them automatically. For example,
is read as if it were
and produces -0.41615 either way. This conversion goes from exactness to approximation, so we may lose a little accuracy: real numbers measure to an accuracy of about 1 part in 16000000, so they'll have trouble telling the difference between 16000000 and 16000001. But this is unlikely to matter, since real numbers are used only for approximate calculations anyway.
The ordinary arithmetic operations work on both numbers and real numbers, so the meaning of "N plus M" depends on the kinds of N and M. In general the rule is that if either is a real number then the other one is automatically converted, and real arithmetic is used. So:
In general we can't do the reverse, that is, we can't silently use a real number where a number is expected. For example,
makes no sense. But we can explicitly convert them:
This phrase performs signed addition on the given values, whose kinds must agree, and produces the result. Examples:
We probably ought to bear in mind that the limited range of "number" means that the nearest whole number might not be all that near. For example:
because 2147483647 is the highest value a "number" can have.
Finally, real number can also store two interesting not-really-number sorts of value. First, we have
which are used to keep track of what happens when we divide by really small quantities. It's mathematically impossible to divide by 0, but this can be hard to avoid when we're using real numbers, because they're only approximately stored – so it's not always possible to say whether they're exactly 0 or not. So in real number arithmetic,
doesn't throw a run-time problem the way that
does. Instead, it produces "plus infinity". Infinity behaves roughly the way we might expect – for example, "2 divided by plus infinity" produces 0.0 – but once it comes into a calculation the result probably lies on some extreme and won't be very useful. Amusingly, the following is correct Inform syntax:
and evaluates of course to 2147483647. We can use the adjectives "infinite" and "finite" to talk about these numbers: plus infinity and minus infinity are infinite, everything else is finite.
The same problem occurs for calculations like square roots. It's impossible to take the square root of a negative number, but we don't want to throw a run-time problem, because approximation means we can't always guarantee to stay the right side of 0. So for a few calculations like this, Inform generates what's called a "nonexistent" real number. We can use the adjectives nonexistent or existent to talk about this. Every number mentioned on this page so far is "existent", including the infinities. The only way to get a nonexistent number is to carry out an impossible mathematical operation such as
(The design of "real number" here follows well established trade-offs for scientific computing. Inform follows the IEEE-754 binary32 standard for floating-point arithmetic, so Inform's "real number" behaves very like the "float" type in C, C++, Java and similar programming languages. A "nonexistent" number is what's often called a NaN – a Not-a-Number.)
This text substitution writes out the number to the given number of decimal places. Examples:
produces "The semicircle is roughly 3.142 paces around." The number of places can only usefully be from 1 to 8. Note that, for example, "[1.235 x 10^-7 to 3 decimal places]" produces 0.0; "[1.235678 x 10^8 to 3 decimal places]" produces "1.236 x 10^8".
This text substitution writes out the number in decimal form, that is, avoiding "x 10^n" even for very large or very small quantities. For example,
produces 123457000.0 rather than 1.23457 x 10^8. This can look pretty extreme: for example, "[1.8983 x 10^27 in decimal notation]", the mass of the planet Jupiter in kilograms, produces 1898296960000000000000000000.0.
This text substitution writes out the number in decimal form, but rounding to the accuracy given.
This text substitution writes out the number in scientific form, that is, using "x 10^n" even for easy-to-judge quantities. For example,
produces 7.29927 x 10^-3 rather than 0.0073. This can look odd: for example, "[pi in scientific notation]" comes out as 3.14159 x 10^0 rather than 3.14159.
This text substitution writes out the number in scientific form, but rounding to the accuracy given.
We are allowed to perform about the same operations on numbers as are provided by a simple office calculator, starting with addition, subtraction, multiplication and division. We can use the traditional typewriter symbols for these, +, -, * and /, or can spell them out in words as "plus", "minus", "times" (or "multiplied by"), and "divided by". Definitively:
This phrase performs signed addition on the given values, whose kinds must agree, and produces the result. Examples:
This phrase performs signed subtraction on the given values, whose kinds must agree, and produces the result. Examples:
This phrase performs signed multiplication on the given values, whose kinds must be dimensionally compatible, and produces the result. Examples:
This phrase performs signed division on the given values, whose kinds must be dimensionally compatible, and produces the result. Examples:
Division rounds whole-number values down to the nearest whole number. An attempt to divide a number by 0 will cause a run-time problem message; but an attempt to divide a real number by 0 will instead produce plus infinity or minus infinity.
This phrase performs signed division on the given values, whose kinds must be dimensionally compatible, and then produces the remainder. Examples:
It is mathematically impossible to divide by 0, so any attempt to find the remainder after dividing a number by 0 will cause a run-time problem message. For a real number this won't arise and the remainder will usually be 0.0.
The verbal and symbolic forms of these phrases are equivalent:
It's probably better style to spell them out in full when writing text, and keep the symbols for writing equations, as we'll see later on in the chapter. (If we do use the symbols, then spaces around them are obligatory: to Inform, they are words which just happen to be spelt with symbols instead of letters.)
Arithmetic often produces fussily exact answers which seem inappropriate in a conversation. Nobody says "Steeple Barton is 7.655 miles down the road", but "Steeple Barton is eight miles down the road" sounds perfectly normal. In order to make that sort of report easier to make, Inform provides another arithmetic operation, one that's not found in most computer programming languages:
This phrase rounds the given value off, rounding upward in boundary cases. Examples:
Inform has very few mathematical functions built in as phrases, because these aren't very often needed in story-telling. But it does provide these:
This phrase produces an approximate square root, to the nearest integer, of the given value, which must be of a kind which has square roots. Example:
Trying to take the square root of a negative number will cause a run-time problem, because then we can't even nearly solve it.
(Warning: this is slow to compute if the Z-machine setting is used. For best performance, use Glulx.)
This phrase produces a square root, as accurately as a real number can hold it, of the given value, which must be of a kind which has square roots. Example:
The real square root of a negative number is nonexistent.
This phrase produces an approximate cube root, to the nearest integer, of the given value, which must be of a kind which has cube roots. Example:
(Warning: this is not very accurate if the Z-machine setting is used. For best performance, use Glulx.)
We can compare numbers using either the traditional computer-programming symbols, or using words:
and similarly for "greater than", "at least" and "at most", with the symbols ">", ">=" and "<=". But we are not allowed the equals sign: for that we need only use "is" -
If the last section provided a basic office calculator, this section and the next provide the more exotic rows of buttons found on a scientific calculator. All of these are done using real number arithmetic. To start with some dull ones, here are two ways to round off numbers:
Produces the smallest integer value greater than or equal to the one given. Examples:
(Note that the result is still a real number; it simply has no fractional part any more.)
Produces the largest integer value less than or equal to the one given. Examples:
(Note that the result is still a real number; it simply has no fractional part any more.)
Two more easy functions:
Removes the sign from a value, leaving positive numbers alone but making negative ones positive. Examples:
Calculates 1/x, that is, divides up 1 into this many pieces. Examples:
Now for taking powers. In general we have:
Computes x to the power y. Examples:
In the words of the Glulx specification document (section 2.12), "the special cases are breathtaking": if you need to know exactly what, say, "minus infinity to the power Y" will do for different cases of Y, refer to the details of the "pow" opcode.
To compute square roots, it's more efficient to use "real square root of X" function than "X to the power 0.5", though both work. To obtain the Nth root of X, we might use:
being careful to use "reciprocal of N" rather than "1 divided by N" to make sure we're using real and not integer arithmetic.
Similarly, the following is more efficient than "e to the power …", but equivalent to it:
Computes e to the given power, where e is the base of natural logarithms. Examples:
The reverse of taking powers is taking logarithms.
Finds what power the base would have to be raised to in order to get this value. Examples:
Logarithms of zero or negative numbers are nonexistent. Note that "logarithm to base 10 of …" is what most calculators call simply "log", but Inform doesn't: it uses "log" for natural logarithms.
Finds what power e would have to be raised to in order to get this value. Examples:
Logarithms of zero or negative numbers are nonexistent. This is the function which most calculators label as "ln", for "log natural", but in mathematical and scientific papers it's more often written "log", and Inform follows that convention.
We have twelve functions left to cover, though they are all closely related.
Inform measures angles in radians, a convention in which the angle for a half circle is pi, and a right angle is pi divided by 2. This is better from a mathematical point of view, but in practice most people think about angles using degrees, where 180 degrees is a half-circle and a right angle is 90 degrees. This phrase helps with that by converting from degrees to radians: in other words, it multiplies by 0.0174532925, since that's roughly 1/180th of pi. Examples:
The length of the upright of a right-angled triangle with this angle and a hypotenuse of length 1, where angle is measured in radians. Examples:
The length of the base of a right-angled triangle with this angle and a hypotenuse of length 1, where angle is measured in radians. Examples:
The ratio of the upright length to the base length in a right-angled triangle with this angle and a hypotenuse of length 1, where angle is measured in radians. Examples:
The inverse of the sine function.
The inverse of the cosine function.
The inverse of the tangent function.
The hyperbolic sine function, often written "sinh" but pronounced "shine".
The hyperbolic cosine function, often written "cosh".
The hyperbolic tangent function, often written "tanh".
The inverse of the hyperbolic sine function.
The inverse of the hyperbolic cosine function.
The inverse of the hyperbolic tangent function.
Suppose we want to talk about how tall people are. We could just create a "number" property, like this:
But then we would have to write lines like "Isabella has height 68", which nobody would naturally say. What we want is to be able to write "Isabella is 5 foot 8." Perhaps the computer will need to store that measurement as the number 68 in some register or other, but we don't want to know about that.
"5 foot 8" is a complicated notation in a way – it involves both feet and inches – so let's start with a simpler example:
This is a little different to the kinds of value seen so far, which were all created like so:
We can't mix the two styles: a new kind of value will either be numerical at heart ("10kg") or verbal at heart ("blue").
The effect of "10kg specifies a weight" is to tell Inform that this is the notation for writing a constant "weight". So, for instance,
Inform is then careful not to allow weights to be mixed up with other numerical values. For instance, it won't allow "if the maximum load is 400", because 400 is a number, not a weight.
More or less anything we can do with numbers, we can now do with weights. For instance, we can write:
…which will produce the text "A sign declares that the maximum load is 8000kg."
Numerical kinds of value are sometimes called "units", because one of their main uses is to allow us to write quantities using scientific units such as kilograms. But they have other uses too. We have a great deal of freedom in creating notations like "10kg", or "4 foot 10" – the main thing is that new notations must not already mean a value. So "10 specifies a weight" will not be allowed, because 10 specifies a number already.
By default we can only write whole-number values. As we've seen, Inform can handle both integer (whole-number) and real arithmetic, and they each have their advantages. The default here is to use whole numbers, so
will store only whole numbers of kilograms (unless clever scaling tricks are used: see the next section). That may be fine, but if we need to handle a wider range of weights, or do scientific calculations that need to be more accurate, this is better:
Here Inform can see from the ".0" in the prototype number that real numbers will be involved. (It needs to be ".0" not, say, ".5" because that could be read as a different sort of notation.) We can still write "8000kg", but we can now also write "1.9885 x 10^30 kg" (the mass of the Sun) or "9.109383 x 10^−31 kg" (the mass of an electron). On the other hand, any calculations we do will be limited in accuracy to about 6 to 9 decimal places, exactly as for real numbers.
By default we can only write positive values when whole numbers are used. Sometimes it is unnatural to write negative values, and so Inform will issue a Problem message if this is tried – for instance, Inform would not allow us to write a weight of -4 kg. (This doesn't mean that arithmetic on units is forbidden to get a negative result: we may want to work out the difference between two weights. Inform's Problem message is simply to try to prevent the accidental writing of incorrect values.) If we do want the ability to write negative values in the source text, we signal that in the notation itself:
That alerts Inform that both positive and negative values for this unit make sense.
If we set up a spread of multiple notations (see the next section) then this is automatically enabled, because then we're clearly dealing with proper physics, where negative values are common; and similarly if we use real numbers (as above).
Going back to our weight example:
The notation here is a single word, even if it contains digits as well as letters – "10kg". But it doesn't have to be one word. These would have worked, too:
In fact, we are allowed to have all three at once, as alternatives:
If we often have to deal with large weights, it becomes a little cumbersome to keep on writing something like "80000kg". An engineer would write "80 tonnes" for this. Similarly, we wouldn't like road maps to use light years, or speed limit signs to use furlongs per fortnight. So it's sometimes useful to provide a spread of different notations, at different scale factors, for the same kind of value. Here's one way of setting up the tonne, that is, the metric ton:
This really is an alternative way to write the same thing: for instance, Inform will allow "25kg plus 3 tonne", the result being "3.025 tonne".
That's all very well, but a value like "3 tonne" reads a little oddly, even if it's correct in theory. Outside of scientific journals with old-school copy editing, most people would write "3 tonnes", not "3 tonne". Here's a better try:
Now Inform will not only recognise both forms, but also use the right one when printing back.
As we've seen, there are two ways to store values like lengths or weights: as whole numbers, or as real numbers. If we prefer to use whole numbers, or if real numbers aren't available (for example if we're using the Z-machine setting), then we might run into an awkward problem: when we write
we make this correspond to the whole number "1", and that means Inform can never handle weights smaller than 1 kg.
But as we've seen, we can provide differently scaled notations for the same unit:
And this allows us to write "0.45km" instead of "450m", if we want to, both having the same effect. "0.45km" doesn't make a real number, despite the decimal point – it's simply another way to write "450m", stored internally as the whole number 450.
Just as we can scale up, so we can also scale down:
Now we have a spread of three notations, so "3cm", "0.03m" and "0.00003km" all mean the same thing. But something quite interesting happened at the same time: Inform realised that we want to know lengths to a greater accuracy than just a whole number of meters.
If we're using whole numbers, and we want to resolve down to very small values, that reduces the size of the largest value we can have. For instance, with the Glulx format setting, writing just
gives us a range of 1m up to 2147483647m, which is plenty – it's about six times the distance from the Earth to the Moon. Going down to centimeters:
gives us instead 1cm up to 21474836.47m, which is still enough to represent any possible distance on the Earth's surface. For instance, London to Sydney is about 17000000m.
Left to itself, Inform chooses the scaling for a unit so that it can represent exactly 1 of the smallest notation – so in our example Inform resolves down to 0.01m, not 1m, in order that it can represent 1cm accurately. But we can also fix the scaling ourselves:
Notice "scaled at", not "scaled down" or "scaled up" – this is now the first notation for length, so there's no existing notation which it could scale up or down. Anyway, now the range is 0.0001m, the width of a human hair, up to 214748.3647m, which is about 130 miles. (The Kinds index automatically keeps track of the range of values represented exactly.) The "scaled at" feature is meaningless if we're using real numbers, so it throws a Problem message.
Finally, for a really deluxe kind of value, we can also provide "equivalent" notations. The idea here is that we might want both miles and kilometers to work, even though they aren't direct scalings of each other. We can only do this approximately, but:
Equivalent notations are never normally used in printing values back (but see the next section) – we wouldn't want Inform to print a sequence of values such as "1.6km", "1.65km", "1.056 miles", … in an effort to be helpful.
When it has a variety of notations to choose from, Inform will normally use the neatest one given the size of the value it is printing. Suppose we've set up "weight", with three notations:
Inform will then print back values like so:
Note the way Inform goes into decimal places in order to talk about 2500kg in terms of tonnes rather than kilograms – it is minimising the integer part of the unit, but trying to keep it non-zero. So Inform prefers "45kg" to "0.045 tonnes".
Although Inform's habit of choosing the best notation available is usually just what we want, we sometimes want to make the choice ourselves. For instance, if we were printing out a table of different weights, we might want to give all of them in kilograms, whatever their size. In that case we can, if we want, give names to our different notations:
Now we could write, for instance:
And the figure will always use tonnes now, even if Inform would normally think it odd: "The weighbridge warns you not to exceed 0.001 tonnes." But it will still correctly use "tonne" or "tonnes" as appropriate – what has changed is that instead of choosing from all of the weight notations, Inform now chooses from the notations labelled as "in tonnes".
So now we can invent notations for weight. We could, for instance, write:
And that allows us to write:
But nobody would say it that way: they'd say "The lead pig weighs 45kg." So what we really need to complete our setup is a verb "to weigh".
We have already created new verbs, but none of those methods are quite convenient for this. We want to relate something tangible (the lead pig) to something intangible (45kg), and there's no convenient relation to express this; if we set it up as a condition, we'd get something we couldn't assert, only test. Instead, we'll do something different this time:
Previous definitions like this ended "means the … relation", rather than "means the … property", but the idea is the same. The meaning of "X weighs Y" is that the weight property of X is equal to Y. So we can now write:
And as we saw in the chapter on Descriptions, we can also set up adjectives, comparatives and superlatives:
which creates "heavy", "heavier" and "heaviest".
To sum all of this up, what started out as a simple business of setting a notation for lengths becomes something quite elaborate when we try to match the actual notations used by scientists and engineers. It's all optional, of course, but as we want more and more of this, we might find ourselves with a spread of notations like this:
In addition we might want equivalents for the inch, the yard and the mile; and verbal forms like the meter and the millimeter, and then alternate spellings like the kilometre; and then both singular and plural forms. And that's just length – what about density, area, pressure, velocity and a dozen other physical quantities? After a while these declarations start to look as vastly fussy as a box of presentation cutlery.
Fortunately the whole set is indeed available in a presentation box, and at no extra charge.
(a) The built-in extension "Metric Units by Graham Nelson" sets up a whole range of scientific units, with all the notations we are likely to want. Real numbers are used throughout, so large and small-scale calculations can be carried out quite accurately. Like the other built-in extensions, it has its own documentation and examples.
(b) The built-in extension "Approximate Metric Units by Graham Nelson" does the same but using whole numbers, scaled about right for human situations. This won't be much use for extensive calculations, and won't be as accurate, but it will work reasonably well if real arithmetic isn't available.
We've seen quite enough scientific notation for the time being. There are plenty of other notations used in natural language, for everyday concepts, where people don't use a tidy spread of powers of 10. Instead they use mixtures, with some sort of punctuation or text to divide them. For instance, the running time of a piece of music is easier to follow in minutes and seconds than in seconds alone: old-fashioned LP sleeves used to quote running times in the form 4'33.
The choice of "3" here makes no difference, much as the choice of "10" in the weight examples was arbitrary. But the "59" is significant. Numbers after the first one are expected to range from 0 up to the value we quote – so in this case, the number of seconds can be anything from 0 to 59. Or, for instance:
A specification can contain up to eight numbers like this, but once again we might need to worry about the maximum value which can be stored. For instance, using the 3'59 notation, we can only go up to 546'07 (if we're using the Z-machine format setting) – a little over 9 hours, so the new Tori Amos album will not be a problem, but some of the more punishing German operas might break the bank.
In notations like this, only the first-appearing number part is allowed to be negative, and then only when declared with a minus sign:
Here, the mystery can be negative, but not the enigma.
Notations must not contain double-quotation marks because, even though people did once use these to denote minutes of arc, they would simply confuse programs like Inform's user interface which have to keep track of what is quoted text and what is not. But other punctuation marks are fine provided they occur between two digits. For instance, in
the full stop between the 1 and the 99 is not interpreted as a division of two sentences; and similarly for colons in examples such as
We often need to break up a number specification into its pieces. For instance, suppose we want to know the dollars part of $1.99? We can do this by naming the parts:
We can now find the relevant parts like so. Suppose that "sum" is a monetary value. Then:
are both numbers, so for instance we can
We can also go the other way:
produces the monetary value $4.72. (Note the lack of commas or "and"s, and that the parts have to be given in the right order.) This is really intended to be useful when we manipulate such values in unusual ways:
Declaring the parts of a number specification individually also enables us to tack one or more options onto any of the parts:
This declares that the "cents" part is optional – it will be 0 if not specified – and that if omitted, the non-numeric "preamble" before it should also be omitted. Thus "$3" is now valid and equivalent to "$3.00": indeed it will be the preferred form when Inform prints out a monetary value which is an exact number of dollars. If we had said that "cents" was optional, but not said that the preamble was optional, then "$3." would have been the form – which is less satisfactory.
There is only one other option: "without leading zeros", as in the following.
This ensures that when the ratio 4:3 is printed, it will be printed as "4:3" and not "4:03" as would otherwise happen.
It may be worth noting in passing that number specifications, like all other kinds of value, can be understood in typed commands. (See the chapter on Understanding for more on what can go in such square brackets.) For instance:
This chapter began by mentioning arithmetic, and then went on a long diversion to create scientific units, everyday weights and measures, and other notational conveniences. Putting all of that together, it's time now to calculate something with all of these numerical quantities.
Suppose we invent the idea of weight, and give everything a weight of its own. Most items will have a nominal weight of 1kg, but people will be heavier. Going on actuarial tables, we might say:
and this provides us with "lighter", "lightest", "heavier" and "heaviest" as before. Now we could say "if Peter is heavier than Paul", or even "if Peter is heavier than 75kg", and so forth. We need one more tool:
This phrase produces the total of some property held by all of the values matching the description. A problem message is produced if the values in question can't have that property ("the total carrying capacity of scenes"), or if it holds a kind of value which can't meaningfully be added up ("the total description of open doors"). Example:
That gives us everything we need for a working balance platform:
Note that this only works because we said that "everything has a weight": otherwise it would make no sense to add up the weights of things.
This enables us to get the average weight of a group of things, too:
But we should be careful that this does not accidentally divide by zero, which it will if the platform has nothing on it! As well as the average, we could find the maximum and minimum weights:
We should remember that "the heaviest thing on the platform" may be ambiguous, because there may be several equally heavy things there. That means
will only reliably work if there is no possibility of a tie. A safer bet is:
Forming totals is all very interesting in its way, but it's book-keeping rather than physics. As a glance at any school science textbook shows, the way to apply physics is to work out an unknown quantity – say, the time taken for a dropped ball to hit the ground – by combining known quantities into an equation – the height it is dropped from, and the strength of gravity.
It's a convention centuries old now that textbooks and research papers never describe these equations in running text. Even for simple formulae, we like to write "F=ma", not "let the force be the mass times the acceleration". And the standard way to print this is to break off and display an equation, not to squeeze it into the text as if it were ordinary verbiage. Just as Inform's Tables imitate those in printed books (see the next chapter), so its Equations do.
In this section, we'll use a combination of three equations to work out how soon and how hard an object pushed off a table will hit the floor. First, we'll include Metric Units, to define all of the kinds of value and notations we need.
Now we'll give everything a mass (Metric Units likes to talk about mass instead of weight, but on Earth it's the same thing) and also set up a typical strength for gravity – it's a little less at the poles, a little more at the equator, but this is the conventional approximate value to use.
To a Renaissance scientist, typically living in a walled European town, a cannon ball was a familiar thing, and it often featured in imaginary experiments:
And now we're ready for the three equations. These will all have names, but we could just as easily have numbered them, calling them (say) "Equation 1", "Equation 2" and "Equation 3".
An equation has to take the form of one formula equals another, where each formula is made up from symbols defined afterwards. The symbols can be defined as definite values (as "g" is defined in the Galilean Equation), or just by telling Inform their kinds of value (as "v" and "t" are defined).
Equations are read using standard mathematical conventions. So "x + yz" means that we multiply y and z, then add that to x; "ab/cd" divides the product of a and b by the product of c and d. Multiplication signs can be omitted, just as science books normally do (though we can always write them if we want to, using the asterisk *, as usual in computing). The need for brackets is minimised, with any luck, but we can use them if we need to: "x(y+ab)" is legal, for instance.
One difference between Inform's conventions and mathematical ones, though, is that Inform generally ignores upper-versus-lower-case when reading variable names, so it wouldn't be a good idea to write "F = gMm/r^2" and expect "M" and "m" to be different from each other.
Here is the calculation:
And the result is:
Not all that fast-moving – it's only about 10 mph, ten times slower than one fired by a Renaissance cannon – but half a second wouldn't give you long to get your foot out of the way.
How was that done? The crucial lines are the ones in the form "let X be given by E…", which is a new form of "let".
This phrase creates a new temporary variable, starting it with the value found by solving the given equation. The variable lasts only for the present block of phrases, which certainly means that it lasts only for the current rule. Example:
There is also a more compact syntax, giving the equation explicitly:
When we solve with "let", then, all of the other symbols should either already have values (because they exist as "let" values already made) or else be specified in the line. For instance,
is allowed because "F" is one of the symbols in "F = ma"; of the other two symbols, we have a "let" variable called "m" already – it's the mass of the cannon ball – and we declare exactly what "a" is.
The next calculation is more interesting:
Since the equation here is "mgh = mv^2/2", Inform has to do some algebra to work out "v" in terms of the other unknowns – it's the square root of 2gh, but we don't need to work that out. Inform can't always solve implicit equations – for instance, it can't deduce "m" from this equation – but it's correct on all the easy cases which occur in basic physics, and that enables us to write equations in their most natural form, which is easier to read and understand.
The advantage of setting out an equation formally is that it can be used in many places – we could use Newton's Second Law again for something quite different, for example. But it's a little cumbersome for something simple which we only need once, so this is neater:
Here the equation is written out explicitly instead of being named, but otherwise everything works in the same way.
Equations can also contain many of our standard functions, which are written for this purpose with their standard mathematical abbreviations. For example:
works out x as pi divided by 4, which is to say, 90 degrees. The Phrasebook entries on the mathematical functions give their abbreviations, but here they all are as a list:
As an example, here's the definition of arcsinh given in the Standard Rules:
Something to be a little cautious of: brackets are used in equations to group terms together, and do not mean function application, as they would in a C-like programming language. For example, "sin(1+x)/2" takes the sine of "(1+x)/2": if we want to halve the sine of "1+x", we have to write "(sin(1+x))/2".
The example equations in the previous section carried out quite a lot of arithmetic, but they may have given the impression that Inform always allows arithmetic – which is not true.
This is actually a good thing, because it keeps us from error. For instance, Inform will not allow:
because whatever you get when you square a mass, you don't get a force – in the same way that a length times another length makes an area, not another length. Physicists call this "dimensional analysis", and it often provides clues about which equations are right. Just after the Second World War, someone correctly worked out the explosive power of an atomic bomb without any classified information simply by guessing what values would appear in the formula, and then finding the simplest equation they could appear in.
In general, Inform will not allow numerical kinds of value to be multiplied or divided by each other (or square or cube rooted) unless we give it instructions that this would make sense.
Of course, there's plenty we can still do without any need for such instructions. For instance, going back to weight,
…will produce the text "A sign declares that the maximum load is 300kg." Here Inform knows that it makes sense to multiply a weight by 3, and that the result will be a weight. Similarly, Inform allows us to add and subtract weights, and several different forms of division are allowed:
When we visit the Weighbridge, we find:
Whereas we are not allowed to divide 122 by 10kg: that would make no sense, since 122 is a number and not made up of kilograms. Inform will produce a problem message if we try. Similarly, Inform won't normally allow us to multiply two weights together – but see the next section.
To recap, then, it is forbidden to multiply 122kg and 10kg, not because it could never make sense (a scientist might occasionally multiply two weights) but because the result is – what? Not a number, and not a weight any more. But we are allowed to tell Inform what the result ought to be, and once we have done so, the multiplication will be allowed:
which will turn up as:
And having told Inform that lengths multiply to area, we could also divide an area by a length to get a length: no further instructions would be needed.
The built-in "Metric Units" extension includes all of the standard ways that physical quantities are multiplied, and a good way to see these is to try out one of the Metric Units examples and look at the Kinds index, which includes a table showing how all of this works.
When printed books need to display detailed information in a systematic way, they break off from running text and print a table instead. Inform does the same. Here is a typical example:
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | 1 |
| "Iron" | "Fe" | 26 | 56 |
| "Zinc" | "Zn" | 30 | 65 |
| "Uranium" | "U" | 92 | 238 |
After the two titling lines, each line represents one row in the table, and entries on a line must be separated by at least one tab character. A table must occupy a single whole paragraph, with no skipped lines or missing entries.
The top line is a title, the first word of which must be the word 'Table'. We can then either give a table number (this need not actually be a number: Table C2, or some such, would be fine), or give a name, or both – as in this case. The possible titling formats are:
| Table of Population Statistics |
| Table 2.3 - Population Statistics |
In the last example we could call the table either "Table 2.3" or "Table of Population Statistics".
Each column then has a name, and the contents must all be the same kind of value. In the elements table the "Symbol" column contains only text, for instance, and the "Atomic weight" column contains only numbers. Any kinds of value will do, so long as all the entries in the column are mutually compatible. (For instance, mixing rooms and things in a single column would be fine, as these can be reconciled, but mixing numbers and rooms would not.)
The simplest way to access the information inside tables is to ask explicitly for it, specifying the row number, the column name and what table is to be consulted. So, given our example table
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | 1 |
| "Iron" | "Fe" | 26 | 56 |
| "Zinc" | "Zn" | 30 | 65 |
| "Uranium" | "U" | 92 | 238 |
we can write the following description:
to produce the value "Zn". Or the following will run off some chemical data:
The result of which will be:
Note that the first row in a table is row number 1, and that the last can be found with the phrase:
This phrase produces the number of rows (including any blank rows) in the given table. Example:
Continuing our example of the elements:
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | 1 |
| "Iron" | "Fe" | 26 | 56 |
| "Zinc" | "Zn" | 30 | 65 |
| "Uranium" | "U" | 92 | 238 |
If we want to know the atomic number of Uranium, say, it seems artificial to have to talk about the particular row number where the information happens to be. So we are also allowed to cross-reference, like so:
This results in 26, and similarly
results in "Fe". But we have to be careful:
This is not allowed (it produces an error at run-time), because there is no row with atomic number 27 in this rather limited table. We can check this in advance with the condition:
Or more simply:
The condition "if there is…" can be used with any reference to a table entry: for instance, "if there is a symbol in row 5 of the Table of Selected Elements" would be false, because there are only four rows.
Here is another rather definitive, immutable-looking table:
| Name | Accession | Family |
| "Anne" | 1702 | Stuart |
| "George I" | 1714 | Hanover |
| "George II" | 1720 | Hanover |
| "George III" | 1760 | Hanover |
| "George IV" | 1820 | Hanover |
| "William IV" | 1830 | Hanover |
| "Victoria" | 1837 | Hanover |
| "Edward VII" | 1901 | Saxe-Coburg-Gotha |
| "George V" | 1910 | Windsor |
| "Edward VIII" | 1936 | Windsor |
| "George VI" | 1936 | Windsor |
| "Elizabeth II" | 1952 | Windsor |
But table entries can be changed as freely as variables: that is, any value can be entered so long as it has the right kind. We cannot put a dynasty into the "Name" column, or text in the "Accession" column. The phrase needed is "now … is …", just as it is for properties or variables:
Once we start changing tables, it sometimes becomes useful to check what they contain.
This phrase prints a crude but sometimes useful display on screen of the current contents of the named table. It's intended for authors to see when testing, not for players of the finished version to see.
This text substitution produces a crude but sometimes useful listing of the entries in the currently chosen table row.
This text substitution produces a crude but sometimes useful listing of the entries in the specified row.
This text substitution produces a crude but sometimes useful listing of the entries in the specified column.
The following would be one way to print out a list of recent Kings and Queens:
This works, but is repetitive. We often want to work on a single row for a while, either to change things or think about the contents, and it is tiresome to keep specifying the row over and over again. The following shorthand provides some relief:
This phrase selects the row with the given number. Row numbers in a table start from 1, so
selects the top row.
That allows us to improve the loop:
Actually, as we'll see in the next section, this kind of loop is needed so often that there's a shorthand wording for it.
Note that since "accession" is a column name, "accession entry" means the entry in that column of the currently chosen row. This notation can only be used if a "choose" has certainly already happened, and it is a good idea to make that choice somewhere close by in the source code (and certainly in the same rule or phrase definition) for the sake of avoiding errors. We can also choose rows by specifying something about them, like so:
This phrase selects the first row, working down from the top of the given table, in which the given column has the given value. Example:
A run-time problem message is produced if the value isn't found anywhere in that column.
Sometimes it will happen that a column's name clashes with the name of something else: for instance, if we call a column "apples" but we also have a kind called "apple", so that the word "apples" could mean either some fruit or the column. Inform will generally prefer the former meaning as more likely. In case of such trouble, we can simply refer to "the apples column" rather than just "the apples": for instance, "choose row with an apples column of…" rather than "choose row with an apples of…"
We can also choose a row quite at random:
This phrase makes a uniformly random choice of non-blank rows in the given table. Note that although a table always has at least one row, it can't be guaranteed that it always has a non-blank row, so it's possible for this to fail: if it does, a real-time problem message is thrown.
We very often want to run through a table doing something to, or with, each row in turn, so a special loop is provided for this. Rather than having to write all this out:
We can simply use this instead:
This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, from top to bottom. Blank rows are skipped. Example:
Note that there is no loop variable here, unlike in other forms of "repeat", because it's the choice of row which keeps track of how far we have got.
We can alternatively go backwards:
This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, from bottom to top. Blank rows are skipped.
More often we want a sequence which is neither forwards nor backwards, but which depends on the actual values in the table.
This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, in order of the values in the given column. Blank rows are skipped. Example:
work through the same table in rather different orders. The sequence is lower to higher (small numbers to high numbers, A to Z, and so on); insert "reverse" after "in" to reverse this.
This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, in order of the values in the given column. Blank rows are skipped. Example:
work through the same table in rather different orders. The sequence is higher to lower (high numbers to small numbers, Z to A, and so on); delete the "reverse" after "in" to reverse this.
In a loop like this, the data is not searched very efficiently, which is fine for modest-sized tables like the examples in this chapter, but might be a problem for much larger tables: see the later section on sorting.
These definitions mentioned blankness several times, and that's the topic to cover in the next section.
Sorting for reordering a table to put it into increasing or decreasing order of the entries in any column.
We are allowed to leave certain entries blank (perhaps to be filled in later, perhaps not) by writing "--" instead of the relevant value:
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | 1 |
| "Iron" | "Fe" | -- | 56 |
| "Zinc" | -- | 30 | 65 |
| "Uranium" | "U" | 92 | 238 |
In effect, blank entries don't exist. "--" is not a value, but only a hole where a value might be. It can be useful to check for this:
This condition is true if the entry referred to exists, that is, that is, the space for it in the table is not blank. Examples:
This condition is true if the entry referred to does not exist, that is, the space for it in the table is blank. Examples:
An entire column of blank entries "--" is problematic:
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | -- |
| "Iron" | "Fe" | 26 | -- |
| "Zinc" | "Zn" | 30 | -- |
| "Uranium" | "U" | 92 | -- |
Inform is unable to work out what kind of value should go into the "atomic weight" column here, since it has no examples to guess from. We can get around this by writing in the name of a kind of value:
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | a number |
| "Iron" | "Fe" | 26 | -- |
| "Zinc" | "Zn" | 30 | -- |
| "Uranium" | "U" | 92 | -- |
That top entry in the "atomic weight" column is also blank, but now Inform knows that anything put into the column in future will be a number.
If there are many rows, and perhaps several blank columns, it would become very tedious to have to keep typing out "--". So this is optional at the end of a row: it remains compulsory for a blank value appearing in between two values which aren't blank. This is the general idea:
| Element | Symbol | Atomic number | Density | Specific gravity |
| "Hydrogen" | "H" | 1 | a number | a number |
| "Iron" | "Fe" | 26 | ||
| "Zinc" | "Zn" | 30 | ||
| "Uranium" | "U" | 92 |
There is no difficulty about entirely blank rows: or rather, the only difficulty is once again that they are boring to type out. We can avoid the necessity by appending "with … blank rows" at the foot of the table:
| Element | Symbol | Atomic number | Atomic weight |
| "Hydrogen" | "H" | 1 | a number |
| "Iron" | "Fe" | 26 | -- |
| "Zinc" | "Zn" | 30 | -- |
| "Uranium" | "U" | 92 | -- |
(These words cannot be placed in between rows, but only at the bottom.) And indeed the table can start out completely empty:
| Element (text) | Symbol (text) | Atomic number (a number) | Atomic weight (a number) |
Blank rows are useful because they enable us to add new data to a table. In effect, they are invisible when not used. A repeat loop like
automatically skips blank rows, so it would initially do nothing at all. Similarly, choosing a "random" row will never choose a blank one.
A convenient way to test if a table contains non-blank rows is to use the built-in adjectives "empty" and "non-empty". So:
tests whether all of its rows are blank; if even one cell contains a value then the table is "non-empty".
Writing in new rows is simple, once we can find space for them:
This phrase chooses a row in the given table which is currently blank under every column. A run-time problem message is issued if no rows are blank. Example:
To avoid problem messages, it can be important to worry about free space. To that end we can not only find the number of rows (as we have already seen) but also the number currently blank and not blank:
This phrase produces the number of rows in the given table which are entirely blank (that is, blank under every column).
This phrase produces the number of rows in the given table which are not entirely blank (that is, at least one column has a value in this row).
"Filled" here really means "non-blank": a row can be filled in this sense even if only one of its values exists. Since every row is either blank or filled, it must be true that:
add up to "the number of rows in Table 3".
We've seen that blank entries can be filled with values using "now":
But the same method can't be used to put blanks back, since a blank is not a value. Instead:
This phrase replaces the entry referred to with a blank, erasing any value previously stored there. Example:
These more destructive phrases need a steady hand:
This phrase replaces the currently chosen row with blanks, erasing any value previously stored under any of the columns. Example:
This phrase replaces the currently chosen column with blanks, erasing any value previously stored in any of the rows. Example:
This phrase replaces every row of the currently chosen table with blanks, erasing any value previously stored anywhere in it. Example:
This is only really useful when a Table is being used to hold working space for some calculation or other.
The three ways to sort a table correspond loosely to the three different orders in which tables can be repeated through. First:
This phrase rearranges the rows of the given table so that the non-blank rows occur at the top, in a uniformly random order, and any blank rows at the bottom. Example:
Secondly:
This phrase rearranges the rows of the given table so that the non-blank rows occur at the top, so that the given column has ascending order, and any blank rows at the bottom. Example:
Ascending order means 1 up to 10, say, or A up to Z, with blank values coming last.
This phrase rearranges the rows of the given table so that the non-blank rows occur at the top, so that the given column has descending order, and any blank rows at the bottom. Example:
Descending order means 10 down to 1, say, or Z down to A, with blank values coming last.
How sorting is done depends on the contents of the column being sorted on. If it holds numbers then numerical order is used, with 2 coming before 7, and so on. (And similarly for real numbers, though the existence of infinities makes this more interesting.) If times are sorted then they are sorted from midnight to midnight, following the "is greater than" relation, not with 4 AM as the zero point, as with "is after".
If text is sorted then alphabetical order is used, though this doesn't always come out the way you might expect, because upper case and lower case letters are treated as different: A-Z come before a-z, and accented letters such as é come after the regular alphabet. (What's happening here is that Inform is sorting on raw character values, not performing the full Unicode collation algorithm, which would be too slow at run-time.)
Note that blank values will always be placed below non-blank ones, and entirely blank rows last of all. This is true even if we use "reverse".
The method of sorting is "stable", that is, if two rows have the same value then they will stay the same way round in the sorted table, rather than being swapped over. For example, if we sort this into reverse index order:
| Index | Comment |
| 1 | "Originally row 1" |
| 2 | "Originally row 2" |
| 2 | "Originally row 3" |
| 3 | "Originally row 4" |
then we get
| Index | Comment |
| 3 | "Originally row 4" |
| 2 | "Originally row 2" |
| 2 | "Originally row 3" |
| 1 | "Originally row 1" |
As a result note that repeating through this sorted table goes through the original rows in order 4, 2, 3, 1; whereas repeating through the original table in reverse order goes through in order 4, 3, 2, 1. (This is all to explain the word "loosely" in the opening sentence of this section.)
Tables are especially useful for combining a run of basically similar rules in a simple and concise way. The "listed in" condition, as in
looks through a given table (here "table of treasures"), in a given column ("item"), to see if a given value is present ("the newfound object"). If this is successful, the row where it was found is automatically chosen; but if not, note that any existing row selection will be lost, so make use of the row only if the test succeeds.
We can similarly use "… listed in …" in a description used when specifying an action. Thus:
This assumes a table in the following shape:
| Item | Value | Time |
| brooch | 5 | a time |
| tiara | 8 | -- |
| coronet | 10 | -- |
In effect the table has allowed us to combine three very similar rules into one. The time column records the first time at which the item has been picked up, which starts out blank since at the start of play it has never been picked up. This enables us to award the appropriate number of points on the first occasion only.
When double-quoted matter appears in a column of a table, Inform will normally treat that as text for printing out. The exception is when the column is called "topic", where it is treated as text for comparing against what the player has typed. There is really only one operation allowed with topic columns, the "…listed in…" construction, but fortunately it is the one most often needed.
Let us suppose that the Sybil has a penchant for telling passers-by which is the Greek muse for what. We might write:
We can then provide a simple table giving her responses:
| Topic | Muse |
| "calliope" | "epic poetry" |
| "clio" | "history" |
| "erato" | "love poetry" |
| "euterpe" | "music" |
| "melpomene" | "tragedy" |
| "polyhymnia" | "sacred poetry" |
| "terpsichore" | "dancing" |
| "thalia" | "comedy" |
| "urania" | "astronomy" |
| "monica" | "tidiness" |
| "phoebe" | "massage" |
| "rachel" | "oval hair-cuts" |
Topics can use the full range of abilities of the "understanding" system which Inform uses to parse text, and which will be the subject of a later chapter. For now, note that the Sybil's topics might equally include "flora/eve" (matching the single word "flora" or the single word "eve"), or something more elaborate such as:
Understand for the system Inform uses to parse text.
The phrase above expects to see a table like this one:
| Points | Citation | Time |
| 1 | "pride" | a time |
| 3 | "anger" | |
| 2 | "avarice" | |
| 4 | "envy" | |
| 1 | "lust" | |
| 2 | "gluttony" | |
| 3 | "sloth" |
The middle column records the tasks to be achieved, the first column records the points on offer for each: the final column, initially blank, will store the times at which the tasks are first achieved.
The first time we record "gluttony" as achieved, 2 points will be awarded and the time will be logged in the Table, but on all subsequent occasions nothing will happen. So the combination of the phrase and the Table will look after a scoring system based on achieving specific goals (probably not the seven deadly sins, of course). We can, if we choose, use the same system to display a log of recent accomplishments:
So far, we have always used fixed table names when referring to tables: for instance in source like "sort the Table of Recent Monarchs in accession order", we refer to the "Table of Recent Monarchs", a definite and explicitly named table.
With a little care, however, we are allowed to have variables which themselves hold the names of tables. This opens up the possibility of more elaborate ways of storing and interconnecting information in table form, but is probably best avoided until it becomes necessary.
For example, suppose we have two different tables with the same basic structure:
| word | score |
| "muzjiks" | 128 |
| word | score |
| "quartzy" | 126 |
| "squeezy" | 126 |
We could then record which one of these tables to use in a variable:
Note that for this purpose, the kind of value is a special kind called "table name", not "table". (The word "table" already has too many meanings and we must be careful to avoid ambiguities here.) We could make use of this as follows, for instance:
which produces text such as
Suppose we need to create a collection of items which differ in their properties, but are basically part of a larger pattern. For instance, here we set up what we need to make a collection of coloured shirts:
Now we have the pattern, but making the actual shirts is tedious and repetitive:
And so on. Instead, we can use a table to abbreviate all of this:
| jersey | year established | citation |
| a yellow jersey | 1919 | "race leader" |
| a polkadot jersey | 1933 | "King of the Mountains" |
| a green jersey | 1953 | "highest point scorer on sprints" |
| a white jersey | 1975 | "best cyclist aged 25 or less" |
The first column provides names for the new things to be created. Subsequent columns provide property values. Note that we did not need to say that jerseys have a number called "year established" because Inform is able to infer this from the column heading and the presence of numbers in the column; similarly for "citation". Lastly, note that if any entry is blank (written "--") then that particular property is simply not set for that particular item.
Note that Inform reads articles such as "the" or "a" in the first column just as it would when something is created with any other sentence.
It's even possible to define kinds this way, though it's rare to need to create many kinds at once. (See the worked example "Reliques of Tolti-Aph" at the Inform website. There's no special syntax needed: rather than saying "Some jerseys are defined by…" we would say "Some kinds of jersey are defined by…")
Just as we can define many similar things (or kinds) using a table, we can also define a whole run of new values. Again, this avoids unnatural prose like
We can give these new values properties, too. For example:
| planet | semimajor axis |
| Jupiter | 5 AU |
| Saturn | 10 AU |
| Uranus | 19 AU |
| Neptune | 30 AU |
| Pluto | 39 AU |
creates five values of the kind "planet", but it also makes a property called "semimajor axis" which belongs only to these five values. Thus:
produces "Pluto orbits at 39 AU." We can both use and change this value:
Similar properties would be made for each column of the table after the first (there can be any number of properties, including none). Because the values are created first, before the rest of the table is gone through, we can even use "planet" as one of the values of properties:
| planet | semimajor axis | centre of government |
| Jupiter | 5 AU | Jupiter |
| Saturn | 10 AU | Saturn |
| Uranus | 19 AU | Saturn |
| Neptune | 30 AU | Pluto |
| Pluto | 39 AU | Pluto |
All of this is intended to be closely parallel to defining a whole run of things, such as the coloured jerseys, using a table, but there are two important restrictions: firstly, when a kind of value is defined by table, the table must contain all of its possible values; and secondly, the column names (after the first) cannot coincide with names of any properties held by any other value (or thing, for that matter). So it is a good idea to give the columns very specific names ("centre of government") rather than vague names which might cause clashes elsewhere ("owner").
Two technical footnotes. In a table used to define a kind of value, blank entries are not left blank: they are filled in with suitable default values. For instance, if the semimajor axis column had been all "--"s except for listing Neptune at "30 AU", say, Inform would deduce that the column was meant to hold a value of kind "solar distance", and would set the solar distances for all of the other planets to be "0 AU". It does this to ensure that "solar distance of P" exists for any planet P.
The second technical note is that we must not sort such a table, because it is used during play to store the properties, and if it were to get rearranged then so would the properties be – with probably disastrous results.
A table is an arrangement for putting information together concisely in a single place, so it might seem odd that we sometimes need to divide it up: but once in a while, we do. Suppose we have:
| planet | semimajor axis |
| Jupiter | 5 AU |
| Saturn | 10 AU |
| Uranus | 19 AU |
| Neptune | 30 AU |
| Pluto | 39 AU |
But then someone in Chile with a telescope the size of God's own teacup notices something a long, long way out, and the newspapers get terribly excited. We can write an addendum:
| planet | semimajor axis |
| Orcus | 39 AU |
| Quaoar | 43 AU |
| Xena | 68 AU |
| Sedna | 524 AU |
This may seem unnecessary – why not simply add extra rows to the original table? – but it allows us to split the table between different parts of the source text, if we want to, or to continue a table which exists only in an extension. (Thus if we were using an extension which involved the planets, and had a table like this one, we would be able to add new planets without changing the extension.)
The name for the continuation must be identical to the original. The continuation has no existence in its own right: Inform simply splices the two (or more) pieces together, exactly as if the table were all in one piece at the place where it first occurred. Thus the above creates only one table, the "Table of Outer Planets", with nine rows. Each column in the continuation must exist in the original, but not every column need be given: those omitted are filled with blank entries. The columns need not be in the same order. Both original and continuations are allowed to quote a number of blank rows: if so, the combined total is used.
At time of writing the International Astronomical Union has not yet consented to name 2003 UB313 after Xena, the Warrior Princess, but this is surely only a bureaucratic delay. (Footnote: on 24 August 2006 it was demoted to dwarf planet status, like the luckless Pluto, and on 13 September renamed Eris; though its moon's official name, Dysnomia, is an ingenious double-meaning to do with the name of Xena's actress, Lucy Lawless.)
Tables can have amendments as well as continuations. The arrangement is much the same: a supplementary table supplies new rows for the original table. But instead of adding the new rows at the end of the original, as a continuation would, an amendment replaces matching rows in the original. (So the original stays the same size.)
The amendment table must have exactly the columns of the original and in the same order. Moreover, each row in the amended table must match exactly one row in the original. For instance:
| moment | outcome |
| 10 AM | "takeover of Mars" |
| 11:30 AM | "canals reflooded" |
| 11:45 AM | "chocolate bar production doubled" |
| moment | outcome |
| 11:45 AM | "volcanic cave production doubled" |
creates a three-row Table of Plans, with reference to the chocolate bars struck out.
Amendment rows may be given in any order. The process of matching a row begins at the left-most column: Inform tries to see if any single row in the original table has a matching entry. If none does, a Problem is issued. If more than one do, Inform then looks at the second column, and so on. For instance:
| feeling | extent | consequence |
| pumped | 1 | "you feel able to run for your life" |
| pumped | 2 | "you feel able to run for President" |
| wired | 1 | "you feel able to run" |
| languid | 1 | "you feel" |
| feeling | extent | consequence |
| pumped | 2 | "you feel able to run for the Nebraska State Legislature" |
Here the amendment is made to the second row of the original table. The value in the leftmost column, "pumped", matches two rows in the original, so Inform moves on to the next column, reads "2", and finds that only one row in the original still qualifies – so that is the one replaced.
For the present, at least, the columns used for matching may only contain: numbers, times, objects, action names, activities, figure names, sound names, truth states and any new kinds of value or units which have been declared.
During play, the computer and the player alternate in writing messages to each other: in the player's case, these are short instructions, usually saying what to do next. A wide range of such "commands" are automatically understood, but these only apply to the standard built-in actions. (This wide range is conveniently tabulated in the Commands part of the Actions index.) If we want the player to be able to command new actions, then we need to specify what is to be understood as what. For this, we supply special sentences starting with the word "Understand".
Suppose we return to the earlier example of a newly created action:
We then supply lines of grammar (as they are called) for Inform to recognise, like so:
As usual, the square brackets indicate something which stands for text, rather than text to be taken verbatim. "[someone]" needs to be the name of anything of the kind "person", for instance (though as usual that person will need to be in sight of the player for the name to be accepted). The first word – in these examples "photograph" – must be something definite, not a substitution like this.
For obvious reasons, this pattern of words needs to match the expectations of the action. Photographing applies to "one visible thing" – the "visible" just means it does not need to be touched, only seen – so neither of these would be allowable:
The first is probably bad because it supplies no things at all, the second is certainly because it supplies two: what we want, of course, is just the one. (The reason the first is only probably bad is that it's possible to tell Inform how to choose the object if the player doesn't: see the "supplying a missing noun" activity.)
In the photography example, we are providing entirely new grammar for an action not ordinarily built in to Inform. But we often want simply to provide alternative grammar for existing actions, or even to put new interpretations on commands that Inform already recognises. For instance:
The inserting action is built in to Inform, but the command "deposit" is not, so this is created as new. It is occasionally useful to put a twist on this:
The clause "(with nouns reversed)" tells Inform to exchange the two nouns parsed, which is necessary because the inserting action expects the noun to be the item and the second noun to be the container, not vice versa.
The following example:
might look as if it makes "access" behave just like "open" when the player types it, but that's not so: "open" can also be used in constructions like "open the door with the brass key", in which case it is understood as the unlocking action. We could add another line to make "access" behave this way too, but if what we really want is to make "access" behave just like "open", it's easier simply to say so:
This is very useful when adding a new command which needs synonyms:
We can check the current stock of commands by looking at the table in the Actions index: for instance, before making "snap" synonymous with "photograph", it might be wise to check that it is not already defined as a command for breaking something.
Suppose we are devising specialist commands for a game of whist, and we want "discard" as one of them. Looking at the table of commands in the Action index, we find that, inconveniently enough, "discard" already has a meaning: it is synonymous with "drop", and while that might be sensible most of the time, it is perfectly wrong now. We need a way to free up "discard" for our own use. We can do that by:
This cuts it loose, so to speak, and ready to be given new meanings. If we check the Actions index again, we find no mention of "discard" – it is now a blank slate – but "drop" is still exactly as it was. We could now say something like:
(If we had declared that "drop" was something new, the whole thing would have happened in reverse, with "discard" retaining all of the original grammar. Inform does not distinguish between a command and its synonym.)
The "… as something new" sentence works even for a command which did not exist anyway, for instance with:
Of course this does nothing – but it is intentional that it generates no problem messages: it means that the sentence can be used to force a command to be fresh and untouched by previous definitions, which might be useful when working with extensions by other people.
It is also possible to clear out all the commands leading to a given action:
The commands "take" and "get" will still exist, but now they'll only have their other senses (for taking off clothes, for getting out of boxes).
We have already seen "[something]" and "[someone]", which are standard examples of "tokens of grammar" – patterns matched by suitable named things. There are several other standard tokens, provided not so much from necessity but to allow the story parser to be more graceful and responsive. "[someone]" matches the same possibilities as "[a person]" would, but the parser handles it a little better in cases of failure. These special tokens are best explained by looking at some of the examples in the standard grammar, which can be browsed in the Index of any story.
Here we expect that the named item will be one that is held by the player, and the parser will use this to resolve ambiguities between names of things carried and not carried. (If the action is one which positively requires that its noun be something carried, a command matching this token against something not carried will generate an automatic attempt to take it.)
"[things]" is like "[something]" but allows a list of items, or a vague plural like "all", to be typed. The result will be a sequence of actions, one for each item thus described. "[things preferably held]" is the analogous token for "[something preferably held]".
"[things inside]" matches only what is inside the second-named thing, and ensures that (for instance) the command "take all from box" does not also try to take the box.
Similarly, "[other things]" will allow anything except the second-named thing. (Like "[things inside]" it is really only needed for handling containers.)
Finally there is "[any things]", which should be used only with care. This is like "[things]" but with no restriction at all on where the item comes from: it might be invisible, or from a different room, or out of play altogether. If we use this, we had better remember that it would match ALL, with quite extravagant consequences.
Most actions involve items: taking a vase, perhaps. As we shall see, they might also involve values, or a mixture of the two: turning a dial to 17 would involve both a thing (the dial) and a number (17). A few of Inform's built-in actions, however, can act on any text at all. For instance, asking the Sybil about the Persian army would involve a thing (the Sybil) and some text ("Persian army"). Inform does not try to understand automatically what that text might mean, or to relate it to any items, places or values it knows about: instead, Inform leaves that to the specific story to work out for itself, since the answer is bound to depend on the context. (In the chapter on Tables, we saw ways to compile tables of responses to particular topics of conversation.)
The token for "accept any text here" is just "[text]". For instance, if we create an action with:
We can then provide grammar for this action like so:
When text like this is successfully matched, it is placed in a value called "the topic understood". (The term "topic" is used traditionally, really: most of the times one needs this feature, it's for a topic of conversation, or a topic being looked up in a book.)
The fact that "[text]" can match anything means that it's difficult to tell which version of a command was intended if they disagree only from a "[text]" onwards. For example, given:
…Inform will in fact try the second possibility first, as being the more specific, but the result may freeze out the first possibility altogether due to autocompletion of commands.
Almost all actions apply to things: the player picks them up, pushes them, looks at them and so on. We only occasionally need to recognise other kinds of value, but when we do, we can. For instance:
The substitution "[a number]" matches any number (actually any whole number that is not too large) typed by the player. Inform checks the various kinds being used to make sure that everything matches, so, for instance, this would be disallowed:
Ordinarily, if we write
then the "[something]" will only match what is within reach or sight: this is the concept of "scope", which is what prevents a player from spookily acting on objects from a distance. The parser itself prevents the manipulation rules from ever being invoked on such distant items, which is as it should be.
Sometimes, though, we positively want to allow this possibility. If we use the special word "any", as in
then any door, anywhere in the model world, can be allowed in the player's command. (Of course, the manipulation rules may not do what the player hopes: all that has happened is that the command is now possible to type.) The "any" can be followed by any description of items or rooms, and the latter opens up new possibilities, since rooms are ordinarily never allowed to be named in the player's commands.
For example, the following gives the player the ability to walk between rooms without giving explicit directions of movement.
(This is really only a sketch: in a finished work, "go to" would produce helpful errors if non-adjacent but visited rooms were named, and we might also worry about rules applying to movement, because the method above will circumvent them.)
As might be expected, "[anything]" means the same as "[any thing]"; "[anybody]" and "[anyone]" mean the same as "[any person]"; and "[anywhere]" means the same as "[any room]".
So far in this chapter, Understand sentences have been used to give names to actions, but they can also be used to name objects – in particular, things and rooms.
This normally happens automatically. For instance, writing
makes ST BERNARD refer to the dog, and MONASTERY CAGES refer to the room. But sometimes, as here, that isn't really enough. Why shouldn't the player type EXAMINE DOG? One way to allow this is to write:
Matters become more complicated when the player wants to refer to more than one object at once. When a kind is created, and the source text constructs multiple duplicate items of that kind, Inform generates a plural of the kind's name in order to understand commands referring to these multiples. For instance, given…
…the player can type TAKE DUCKS to try to pick up all four.
Once again the automatic behaviour can be enhanced:
Now TAKE BIRDS and TAKE DUCKS are equivalent. Plurals can even, strange as it may seem, be given for single things:
And now TAKE BIRDS tries to take all four ducks and the magpie too.
In many cases, if K is the name of a kind of value, then Inform automatically makes an Understand token called "[K]" which matches only values of K. An example is "[number]", which matches text like 203 or SEVEN. There is a chart of the kinds of value in the Kinds index for a project, showing which ones can be understood in this way.
In particular, any newly created kind of value can always be understood. We make good use of that in the example story "Studious":
Note the way we can refer to the limb mentioned by the player as the "limb understood". Similarly, we could talk about the "number understood" if the value parsed had been a number, and so on.
One of the built-in kinds of value is worth special note: time. A time can hold either a specific time of day, such as 10:23 PM, or a duration of something, such as 21 minutes. The "[a time]" token matches times of day, such as 10:15 AM or MIDNIGHT. But 10 MINUTES wouldn't be recognised by "[a time]" since it isn't a specific moment in the day. To get around this, an alternative version called "[a time period]" is available. So:
would match WAIT FOR AN HOUR or WAIT FOR TWO HOURS 12 MINUTES.
In every example so far, and in almost all practical cases, the first word in a command which results in an action will be something fixed: a verb, in fact. When we write
we are saying that the first word of such a command will always be "photograph". Occasionally, though, we would like to understand a noun as a command, perhaps in a situation where the command is obvious. If we say:
then the command "examine" will be implicit when the player types a bare noun:
so that the command "ball" has resulted in the action "examining the blue ball".
This is a feature which should be used sparingly, since it could easily lead to confusion if not carefully explained to the player. By default, it is not used at all.
It also has what may be a serious limitation: verbless commands like this work only when typed by the player as actions to follow – they do not work as instructions for other people. So for instance SVEN, BALL would not ask Sven to try examining the ball – instead it would generate the action "answering ball to Sven". (This is because the Inform parser decides whether PERSON, SOME TEXT is a request or just conversation by looking at the first word after the comma to see if it's a command.)
"Understand" can be used to supply new ways to talk about both things and other values. For instance, if we create:
then it can be called "brass", or "lantern", but not "lamp": Inform does not really know what these words mean, and has no grasp of synonyms. We can arrange for "lamp" to work as well like so:
With care, we can do the same trick for entire kinds of thing at once. It is not ordinarily the case that a thing can be called by the name of its kind: if we put a woman called April into a room, then she can usually be called "April", but not "woman". (The exception is when we do not specify any name for her – in that case, Inform will give up and call her just "woman".) So there is not usually any form of words which can refer to anything of a given kind. If we should want this, we have to say so explicitly:
Device is a kind, so now the word "machine" can be used to refer to any device: if there are two in the same place, the result might play out like so:
Similarly, we might conceivably want to allow new ways to recognise values – in this case, a number:
When making complicated names, we need to watch out for the possibility of writing a definition which will cause Inform to go around in circles (something which will show up as a "Too many activities at once" run-time problem). For instance,
will fail because Inform, working left to right, needs to look for every possible object name before it can progress: one possibility is the placebo itself: to check that, it needs to look for every possible object name: and so on, never finishing. A definition like this one very likely matches too much in any case (would we really want to accept PLACEBO SUBSTITUTE or CIGARETTE SUBSTITUTE SUBSTITUTE SUBSTITUTE here, as the definition implies?).
We have already seen "or" used in "Understand" sentences:
In general, any number of alternative forms can be given which are to be understood as the same thing (in this case the colour red). When the alternatives are in any way complicated, "or" should always be used, but a shorthand form is allowed for simple cases where it is only a matter of a single word having several possibilities:
This is shorthand for:
Which in turn is shorthand for:
It's possible also to make that second word optional:
because "--" is read by Inform as "no word at all". If "--" is an option, it can only be given once and at the end of the list of possibilities.
To recapitulate: the slash "/" can only be used between single, literal words, and is best for the wayward prepositions of English ("in/into/inside", and so forth). For anything more complex, always use "or".
We have now made good use of square-bracketed tokens, such as "[something]", in a variety of "Understand…" sentences. It is sometimes convenient to create new tokens of our own, to match whatever grammar we choose: this enables complicated knots of grammar to be used in many different "Understand…" sentences without having to write it all out each time.
For instance, here are new tokens: one for each of two groups of alternative prepositions.
Again, note that the slash indicates a choice between words only, not between entire phrases. For instance, if we write:
then the two alternative forms are "red bird" and "red robin", not "red bird" and "robin". By contrast,
will understand either "red bird" or "robin" but not "red robin". If we want to capture all three forms, we might define
The examples just seen were tokens which simply matched specific words typed by the player, but newly created tokens can also produce values:
Here the "[tint]" token matches, for instance, "colour red" and "blue shade", which would result in the values red and blue, respectively.
Tokens are not allowed to produce more than one value, and if several patterns are given to define them then those patterns have to be compatible. That means the following is disallowed, since it might work out to a colour, or to an object, leaving Inform unable to judge whether an action can safely be applied to the result.
Items are ordinarily understood only by their original given names. For instance, if we have:
then the player could refer to this as "pot", "china pot" or "china". We can embellish this by adding extra forms:
But suppose the pot changes its nature in the course of play? If we have:
So now the player would reasonably expect to call it "broken pot", a wording which would have been rejected before. We can achieve this by writing:
which allows "unbroken" or "broken" to describe the pot, depending on its state. And, since the player might well use a different adjective but with the same idea in mind, we can even add:
This is something of a toy example, but the feature looks rather more useful when there are more pots than just one:
We then have the dialogue:
and so on and so forth.
There are in fact two slightly different forms of this kind of sentence:
The only difference is that in the "describing" case, the property's name alone can mean the thing in question – so "take unbroken" will work; whereas, in the "referring to", the property's name can only be used as an adjective preceding the name of thing itself – so "take unbroken flowerpot" will work but "take unbroken" will not.
Sometimes it makes sense for the name of something to involve the names of other things to which it is related. For instance, if we say TAKE THE BOTTLE OF WINE, we mean that the bottle currently contains wine – if it were the very same bottle containing water, we would call it something else.
For names which must involve related names, a special form of token is provided. For instance, we could say:
and now TAKE BOX OF CRAYONS will work, because CRAYONS matches against "[something related by containment]" for the red box – or it does for as long as the crayons are there. We can have similar matches against relations of all kinds, but have to name the relation explicitly. (See the examples at the end of this section for plenty of cases.)
We can also reverse the sense. If we write:
then TAKE THE BOX IN THE HAMMOCK will work: here, the relation goes the other way, because the box is being contained by the other-named item, rather than doing the containing.
We have now seen several different forms of "Understand" sentence: for instance,
Any of these may optionally have a condition tacked on: for instance,
In principle, "when …" can take in any condition at all. In practice a little care should be exercised not to do anything too slow, or which might have side-effects. (For instance, referring the decision to a phrase which then printed text up would be a bad idea.) Moreover, we must remember that the "noun" and "second noun" are not known yet, nor do we know what the action will be. So we cannot safely say "when the noun is the fir cone", for instance, or refer to things like "the number understood". (We aren't done understanding yet.) If we want more sophisticated handling of such cases, we need to write checking rules and so on in the usual way.
Contexts can be useful to make sense of things having different names depending on who is being spoken to, as here:
With this rule in place FRODO, GIVE ME YOUR RING means that Frodo will know which ring is meant, even if there are a couple of dozen other rings present.
If the name of something has to change completely, perhaps because the player's understanding of events has changed completely, then Inform's standard way of handling names can be a nuisance. When an item or room is created, Inform automatically makes its name understood as referring to it (in fact, it makes each individual word in that name understood). For instance,
means that the player can type EXAMINE BLUE PEACOCK or PUSH SUNDIAL or SHOWME WABE or TAKE BLUE, and so on. This is almost always a good thing, and here there's no problem, because peacocks and sundials are not usually disguised. But here is a case where a disguise is needed:
As this demonstrates, the either/or property "privately-named" makes Inform create a thing or room which starts out with no automatic understandings at all. The name it happens to have in the source text is ignored. If we simply write:
then nothing the player can type will ever refer to it; though he will see it, and even be able to pick it up by typing TAKE ALL.
The reverse property is "publicly-named", which all things and rooms are by default.
Inform has four built-in kinds of object (room, thing, direction and region), and all of those have this either/or property. When we create new kinds, they're normally kinds of those four fundamental ones, so they pick up the same behaviour. But if we create a new kind of object outside of these four, that won't be true unless we make it so:
(Privately-named is a property which only affects how Inform creates the object, and it can't usefully be given or taken away during play. "Understand … when …" is the way to change names during play.)
The pronouns IT, HIM, HER and THEM are constantly adjusted during play, to save the player time when typing commands. If the player types EXAMINE NECKLACE on one turn, it's sufficient to type TAKE IT on the next, and IT will be understood as meaning whatever NECKLACE meant last turn.
All of that happens automatically, but once in a while the result can be unfortunate. Suppose that when the player examines the necklace, a security system automatically drugs her unconscious, and she wakes up in a cell, hours later, and is told that the cell is bare except for a key on the floor. If she types TAKE IT, she clearly doesn't mean IT to mean the necklace any more; she means the key. Inform's parser can't make guesses like this, so the following phrase can be used to help it.
This phrase adjusts the meaning of pronouns like IT, HIM, HER and THEM in the command parser as if the object mentioned has become the subject of conversation. Example: the combination of
might change IT to mean the silver key and HIM to mean Harry "Bunny" Manders, while leaving HER and THEM unaltered.
When the player types an ambiguous reference, we need to work out what is meant. Consider the following source text:
Now suppose the player types GET TOWER. The response will be:
Which is a silly question, exposing our work of IF as something artificial. It's obvious to the author of the source text, and to the player, that the souvenir must be what is meant: but this is not obvious to the computer program running the story. Works of IF gain a subtle feeling of quality from being able to understand ambiguous references of the kind above, and Inform provides us with a way to do this by giving the parser clues in the form of "Does the player mean…" rules. For instance, if we add:
then the response to GET TOWER will now be:
"Does the player mean…" rules look at the actions which are possible interpretations of what the player typed, and grade them according to how likely they seem. (Note that these rules are only ever used to handle ambiguities: if the player unambiguously types GET GREAT EIFFEL TOWER, that will be the action. And the rules are only used where they are able to make a decision: if there are still multiple equally plausible meanings, the parser will ask about all possibilities, not just the most likely ones.) Rules in this rulebook can either decide nothing, or come up with one of the following verdicts:
If there are no "does the player mean" rules, or the rules make no decision on a given possible action, it will be ranked as "it is possible".
We may use these rules to affect all sorts of interaction with a specific object or kind of object, as in
…and so on.
Notice that we can also make rules about actions that apply to two objects, so for instance:
which nicely clarifies THROW POLISH AT POLISH, but does not comment on the likelihood of throwing the can at other things or of throwing other things at the vending machine. Moreover, the (suspected) identity of the first item will be known when the rule is consulted; thus
will tell Inform to prefer not to tie something to itself if other interpretations are available.
But there is a caveat. There are some cases where this mechanism will not in fact help Inform to choose its way out of an ambiguous command, because of the way it parses one noun at a time. It usually needs to understand the first noun before it will even try to make sense of the second. So a rule like:
may not work if the player types THROW POLISH AT TREE and POLISH is ambiguous, because when the parser is trying to understand POLISH, it hasn't yet seen to the end of the command and realised that the second noun will be the tree; so the second noun is unset and the rule won't match.
As a caveat to the caveat, the "inserting it into", "removing it from" and "putting it on" actions have this slightly back to front. These are parsed using the (little-used) "[other things]" or "[things inside]" tokens, and the Inform parser tries to detect the second noun before the first one, since the identity of the first has to depend on the second. So for instance if the situation contains "an oak tree" and also "an oak chest", we could write:
which would successfully make PUT COIN IN OAK mean the chest, not the tree. (Note the way we write "inserting into" without saying anything about what's being inserted, not even that it's "something".)
When the player types a command like DROP ALL, this is (usually) a request to carry out more than one action. After the command parser has decided what constitutes "ALL" (a process which can be influenced using the "deciding whether all includes" activity), it forms up a list and then runs through it, starting an action for each in turn. The result usually looks something like this:
However, by adding rules to the rulebook:
we can take a look at the actions intended, and rearrange or indeed change them before they take effect. To do that, we have to deal with a special list of objects. For two technical reasons this isn't stored as a "list of objects that varies" – first because it needs to exist even in low-memory situations where we can't afford full list-processing, and second because there are times when changing it might be hazardous. Instead, two phrases are provided to read the list and to write it back:
This phrase produces the current multiple object list as a value. The list will be the collection of objects found to match a plural noun like ALL in the most recent command typed by the player. If there is no multiple object, say if the command was TAKE PEAR, the list will be empty: it won't be a list of size 1.
This phrase sets the multiple object list to the given value. The list is ordinarily the collection of objects found to match a plural noun like ALL in the most recent command typed by the player, but using this phrase at the right moment (before the "generate action rule" in the turn sequence rules takes effect).
When inspiration strikes the player, he can usually be relied upon to make a good-faith effort to communicate the new idea: he will guess the right command. If he guesses wrongly, the mistake is probably the author's, because a good author will try to anticipate all possible wordings and make all of them work.
Nevertheless it is sometimes good practice to nudge the player towards the right wording – particularly if the player has the right idea but is not explicit enough: for instance, typing TALK TO JUDGE when we really want to know what is to be said (JUDGE, GUILTY); or if the player tries something like PLAY CHESS rather than MOVE PAWN TO KING 4. Similarly, if we make a casual reference such as "In your childhood days, you loved sliding in stocking feet across this hallway", a player might type SLIDE IN STOCKING FEET: a nice idea, and which deserves a nice response, even though it asks to do something beyond the scope of the story.
Inform provides a simple mechanism for recognising a command but at the same time recognising that it does not properly specify an action. Such commands are called "mistakes", for the sake of a memorable term, but the player has not really behaved badly, and should be helped rather than reproved. For instance:
While that works – the command to "act" is indeed rejected – it is not very good, because no very helpful message is brought up. The following is much better:
Or we could once again insist on a given context:
That still has the drawback that the command "act hamlet" will not be recognised: so the final version we want is probably
since the "[text]" part will soak up any words the player types (or none), meaning that any command at all whose first word is "act" will be matched.
We need to be careful to avoid circular things like this:
This doesn't work because the topic understood isn't set until the line has been understood, but Inform checks the "when…" condition before it tries to understand the line. Indeed, even this:
is unsafe (quite apart from being unwise!) – again, "topic understood" doesn't exist for a mistake, because in a mistake, nothing is understood.
The following is often useful during beta-testing of a new work, though we would not want it in the final published edition. Many authors like to ask their testers not to try anything in particular, simply to play naturally: but to record the transcript of the session, and email it back to the author. The following command is a device to allow the tester to type a comment in to the transcript:
For instance, the tester might type "* DIDN'T WE SAY DARCY WAS TALL?", to which the story would reply "Noted." – and the author can search for such comments when receiving the transcript.
If we are careful, we can make the reply depend on what was typed in the mistaken command:
The care comes in because Inform applies much less checking to mistakes than to other actions, and odd errors will result if we try to refer to (say) "the second noun" in a command which did not have a second noun.
It's probably wise to take particular care if using "as a mistake" with any command which might include the mistake among what the player calls ALL: for example, if "take [sydney harbour bridge]" is understood as a mistake, then TAKE ALL will may result in this, even though the player doesn't intend any such thing.
When several different lines of grammar are supplied to meet the same circumstances, it makes a big difference what order they are tried in. For instance, suppose we have:
The second line is more specific than the first, so Inform takes these grammar lines the other way around: it checks for "open door" before it checks for "door". That didn't matter here, since both lines came out with the same result (the action of photographing), but it matters very much in the next example:
More subtle is a line already seen:
Here Inform puts "on top of" before "on/in/inside", since otherwise only the "on" of "on top of" will be recognised.
Mistakes always take precedence over non-mistakes: this is intended to make sure that
will take precedence over
even if there is, in fact, a character called Mr Nimbus Umbrage so that the command could conceivably make sense.
Finally, there are a few grammars where the number of values produced is different in different lines. For example, the Standard Rules include these among the possible "put" commands:
One produces a single object, the other produces two. Inform gives precedence to the first of these, that is, it tries the one with fewer values first. This is important when reading commands like "PUT MARCH ON WASHINGTON SHIRT ON", and also prevents bogus auto-completions, in which PUT HAT ON might wrongly be auto-completed as if it were PUT HAT ON THE TABLE.
It is poor form to define with negatives, but the first thing to say about activities is that they are not actions. This needs saying because Inform often seems to treat them as if they are, by allowing us to write rules like so:
With this rule in place, someone called "Daphne" will always be described as "Ms Daphne", and so on. The language looks as if we were imposing a rule on an action called "printing the name of", but there is no such action: instead, it is an "activity". To spell out the difference:
Activities allow us to influence or change some of the standard habits of Inform, using rules as flexible and powerful as those applicable to actions, though activities are in several ways simpler and easier.
All activities start, continue for a while and then finish: however, no activity ever runs on for more than a single turn. Several activities can be going on at the same time. For instance, suppose the following is printed as part of the description of a grocery:
At the moment when Inform prints "apple", two activities are under way: "listing contents of the Grocery", and "printing the name of the apple". The sequence of events was in fact:
The golden rule is: if activity B starts during activity A, it must also finish during activity A.
If we ever need to find out, we can always test:
but as we shall see, it's usually simpler to attach "while printing the name" provisos to rules.
The activity "printing the name of something" is the process of printing up the name of something on screen: ordinarily, this means saying the text in its "printed name" property.
As with actions, rules can be attached to activities which change or augment what would normally happen. In fact the situation is simpler, because (unlike an action) an activity almost always finishes, so we almost always do reach its "after" stage. There are also only three rulebooks attached to an activity, as compared with the six affecting an action.
The three rulebooks for printing the name are called "before printing the name", "for printing the name" and "after printing the name", and this is the general pattern. What happens is:
Whereas an action's later stages never take place if an early stage ends unexpectedly, an activity always goes through all three of its stages. Invoking the word "instead" in a before rule for an action will terminate not only the before rules but the whole action: the same thing for an activity will only terminate the before rules, and the for and after rules will take place as usual.
The actual task is usually carried out by one single rule tucked into the back of the "for…" rulebook: it is the rule for printing the name of whatever is concerned, hence the name. Inform's standard activities are all of this pattern: they start out with no "before" or "after" rules, and just one "for" rule.
Why the part about an activity only "almost always" finishing? One reason is that the story might end during it; but another is that it's possible, though uncommon, to abandon an activity partway. Very few of the activities supplied with Inform ever do this, and those that do are noted in the sections which follow.
Rules applied to actions can become baroque ("after going through a door in the presence of an animal when -" and so on and so forth), but activities are again simpler: they only have one possible clause attached, which is called "while". For instance, the following would provide a fairly sledgehammer hint that the sack should not lightly be thrown away:
Any condition can be given after the "while", and we can also specify that another activity has to be going on. Thus:
This nicely distinguishes between contexts where it's appropriate to be more verbose, and where it isn't. Thus:
Activities are all about influencing the standard mechanisms which Inform uses, so it might at first seem that there is no need to create new activities: but on further reflection, quite a lot of the writing of interactive fiction involves creating new and systematic ways to do things, and as soon as we have a general rule, we will want to have exceptions. Inform therefore allows us to create our own activities, giving us ways to influence the operation of our own mechanisms.
There are two kinds of activity: those which relate to a specific value (usually an object but not necessarily), and those which do not. Here are some examples of activities being created:
Inform looks for the clue "something" (or "of something") after the activity's name to see if it will work on a value: so analysing and announcing will do, but assaying won't. If we don't specify a kind, Inform assumes the value will be an object, as if we had written:
As always in Inform, the names of activities are themselves values.
Creating an activity is like creating an action: it automatically makes new rulebooks – "before analysing", "for analysing" and "after analysing" – but they start out empty, so the activity does nothing yet. Just as it does for rulebooks, Inform defines the adjectives "empty" and "non-empty" for activities to test this state:
will be true only when all three of its rulebooks are empty.
A newly created activity never happens unless we take steps to make it do so. We can make an activity happen at any time by writing phrases like so:
This phrase carries out the given activity, which must be one not applying to any value. Example:
This phrase carries out the given activity, which must apply to a kind of value matching the one supplied. Example:
To make the activity do something useful, we need to put a rule into its "for" rulebook:
"The last" is a technicality about rulebooks (see the next chapter) which, put briefly, guarantees that this rule comes last among all possible "for assaying" rules. This is good form because the whole point of an activity is to make it easy for further rules to interfere – so we deliberately hang back to last place, giving precedence to anybody else who wants it.
The "for" rulebook is one where rules stop the activity, by default, when they take effect – in the same way that the "instead" rules stop actions by default. If this causes problems, we can use:
This phrase should be used only in rules in activity rulebooks. It causes the current rule to end, but without result, so that the activity continues rather than stopping as a result of the rule. This is useful for rulebooks (like the "for" rulebook of an activity) where the default is that a rule does stop the activity.
Activities are more useful than they first appear. Every new one provides a context which other activities can observe. We could, for instance, define
so that during assays more technical names are used.
Just as actions can have variables, which are created when the action starts and disappear when it finishes, so activities can also have variables. They are visible to the rules for that activity, and nowhere else. (If the activity should happen a second time within its first run, that second occurrence gets its own copy of the variable, leaving the original untouched.)
Typically it will be useful to set a variable to some default value at the "before" stage, calculate some interesting value for it in the "for" stage, and make use of the outcome during the "after" stage. For instance:
If we have declared a new activity, like "analysing", the normal way to make it happen would be to write
which goes through the whole machinery of rules – before, for, after – and then resumes, the activity having started, taken place and come to an end.
But there are times when it is not convenient to write a suitable "for …" rule, or where we need more control, and do not wish to hand the whole business over to a single phrase. For such times we are allowed to write:
This phrase causes the named activity to become active, and runs its "before" rulebook. The activity must be one which applies to nothing. Example:
In all cases a matching "end the … activity" or else "abandon the … activity" phrase must be reached.
This phrase causes the named activity to become active, and runs its "before" rulebook. The activity must be one which applies to a value of a matching kind. Example:
In all cases a matching "end the … activity with …" or else "abandon the … activity with…" phrase must be reached.
And when we are done:
This phrase runs the "after" rulebook of the activity and then causes it to become inactive. The activity must be one which applies to nothing. Example:
This must only happen to match an earlier "begin the … activity" phrase.
This phrase runs the "after" rulebook of the activity and then causes it to become inactive. The activity must be one which applies to a value of a matching kind. Example:
This must only happen to match an earlier "begin the … activity with…" phrase.
So the usual structure is like so:
This time the activity is ongoing throughout as many phrases as we care to write between the "begin" and "end". The before rules are considered at the time of the "begin …" phrase; the after rules at the "end …".
What, then, of the "for" rules? In the above setup, they would simply be ignored. But we can make them effectual thus
We place the activity's normal behaviour inside the "if"; the condition, "if handling…", is true only if no rule has intervened. This means that we (or other authors using our activity) can create their own for rules to substitute here. If we elsewhere write
that rule will intervene and take the place of whatever we have placed inside the condition.
This should be used only where the given activity has been started with "begin …" and will be finished with "end …". It runs the "for" rules for the activity, and then comes out true if none of those for rules intervened in the handling of that activity. (The activity must be one which doesn't apply to any value.)
This should be used only where the given activity has been started with "begin …" and will be finished with "end …". It runs the "for" rules for the activity, and then comes out true if none of those for rules intervened in the handling of that activity. (The given value must be the one it is being applied to.)
It is also legal to force an early end to an activity with:
This phrase ends an activity at once (without consulting any further rulebooks, including its "after" rulebook). It can only be used with an activity which has had its "begin" but not yet its "end" phrase; it is a drastic remedy best taken only if it is clear that circumstances have changed so that the activity now seems inappropriate. It must not be used during one of the rules for the activity: it can only be used between the begin and for stages, or between the for and end stages.
This phrase ends an activity at once (without consulting any further rulebooks, including its "after" rulebook). It can only be used with an activity which has had its "begin" but not yet its "end" phrase; it is a drastic remedy best taken only if it is clear that circumstances have changed so that the activity now seems inappropriate. It must not be used during one of the rules for the activity: it can only be used between the begin and for stages, or between the for and end stages.
We need to follow three golden rules: all activities must end, they must never last longer than a turn, and if activity B starts during activity A then it must also finish during activity A. We must also be careful to make sure that if an activity applies to something, then it begins and ends with the same something (the pitchblende, in the above example).
Activities tend to be about process, rather than outcome. Many of the things Inform does – printing up lists of items, reading commands from the keyboard, and so on – are done as activities, because that way the process can be nudged a little. Too many works of interactive fiction betray their mechanical nature by making it visible that the general machinery being used does not quite seem natural for this or that situation. Activities enable us to add the many graceful touches which avoid that: which contribute nothing to a work, and also everything.
The rest of this chapter covers every activity built in to Inform, with one section for each. It is intended primarily for reference, but may be worth skimming through at a first reading, to give a sense of the possibilities.
1. When it happens. Frequently – whenever Inform needs to check whether something is visible or not. Nothing should be printed, and the activity needs to run quickly, so it should not (for instance) calculate best routes through complicated maps before getting an answer.
2. The default behaviour. There is no concealment. The ordinary rules still apply, though: the contents of a closed opaque container are invisible because there is a barrier in the way which cannot be seen through, even though nobody is "concealing" anything.
3. Examples. To repeat a number of brief examples given at the end of Chapter 3, where this activity made an early appearance:
The value "particular possession" is the one whose concealment is in question, of course. We can ignore this if someone is invariably secretive:
In general a rule for deciding the concealed possessions of something will decide "yes" if finishes without making a decision, but it's better style to write such a rule in such a way that it always makes a decision.
1. When it happens. Whenever the name of a thing or room is printed, either as part of text visible to the player, or sometimes internally in order to determine something about that name.
2. The default behaviour. For items other than the current player, the "printed name" property is printed out; but for the current player, "you" or "yourself" is printed. (That doesn't necessarily mean that the "printed name" of the player is never used. Suppose there are two people, Alice and Bob, and the narrative switches between them: when Alice is the player, she appears as "yourself" but Bob is "Bob"; but when Bob is the player, he is "yourself" and Alice is "Alice".)
3. Examples. (a) A pen which is described differently in inventories:
"Taking inventory" is a condition which is true if that's the current action and not otherwise, so the effect is that the pen is called "a useful pen" only in inventory listings. "While looking" is a similarly useful one.
(b) Italicising the names of novels:
(c) Telling the time:
(d) Merging containers with their contents:
This example makes use of a special phrase:
This phrase changes the form of an inventory listing, room description, etc., so that it will simply list "a bottle of sand" or "an empty bottle", rather than "a bottle (in which is sand)" or "a bottle (which is empty)". It should be used only when the listing is imminent, and does not have permanent effect.
The clause about not inserting or removing is to prevent messages like "You put the sand in the bottle of sand.", where it's confusing to refer to the bottle as anything other than "the bottle".
1. When it happens. Only when a group of identical items is present in the same place, and are being described jointly with text like "You can see five gold rings here." The activity happens after "five" and before "here." (See the activity "printing a number of something" if the whole phrase needs to be altered.)
2. The default behaviour. The plural name – in this case "gold rings" – is printed out.
3. Examples. (a) Suppose we want to emphasise how nice it is to have more than one gold ring:
(b) If the number needs changing as well, it's necessary to use the "printing a number of something" activity instead.
1. When it happens. Only when a group of identical items is present in the same place, and are being described jointly with text like "You can see five gold rings here." The activity prints the "five gold rings" part. The variable "listing group size" contains the number, which in this example would be 5, and is always at least 2.
2. The default behaviour. The number of items is printed, in words ("five") and then the "printing the plural name" activity is run ("gold rings").
3. Examples. (a) Using this activity is for perfectionists, because the normal behaviour is almost always fine. Still:
(b) Or perhaps:
(c) If the only part needing variation is the plural name, it's simpler and tidier to use the "printing the plural name of something" activity instead.
1. When it happens. When taking inventory, the list is produced by the activity "listing contents of yourself"; when looking, a list of items which do not deserve their own paragraphs is produced by "listing contents of" the location.
And when it doesn't happen. (a) If the Storage Room contains a sideboard and an open shoe box, then "listing contents of the Storage Room" is used to produce the part of the room description mentioning sideboard and box. But if the box in turn contains a pair of brogues, then "listing contents of the shoe box" is not used to say that part. So this works:
But this won't affect room descriptions:
(b) The activity also doesn't happen when, for instance, "[a list of animals]" is printed, because that isn't a list of the contents of any room or location.
2. The default behaviour. The list is printed out.
3. Examples. (a) We have already seen that it can be elegant to elaborate on a description in the context of a list. Here we add "discarded" to a sweet wrapper which is found on the ground.
(b) Lists can be considerably shortened and tidied up if similar items are grouped together. We do this by specifying what should be grouped together before listing contents, using the special phrase "group … together":
The result will be, say, "two utensils (knife and spoon)", if both are found in the same place.
(c) We can less obtrusively group items together like so:
Three special phrases exist for this kind of list organisation:
This phrase causes the objects described to be listed together in a single item as part of an inventory or room description. The effect is temporary, and the phrase should only be used when this list is imminent. Example:
This might produce the list item "fork and spoon".
This phrase causes the objects described to be listed together in a single item as part of an inventory or room description, but giving each individual item its indefinite article. The effect is temporary, and the phrase should only be used when this list is imminent. Example:
This might produce the list item "a fork and a spoon".
This phrase causes the objects described to be listed together in a single item as part of an inventory or room description, summarised with the given text. The effect is temporary, and the phrase should only be used when this list is imminent. Example:
This might produce the list item "two utensils (fork and spoon)".
1. When it happens. Only while listing contents, and only when a collection of items to be grouped together is reached. This in turn happens only if a "before listing contents" rule has chosen it (see previous section). The first item in the group is the one to which the activity formally applies.
The variable "listing group size" usually gives the number of items grouped together in this way, but care is needed if the "something" covers multiple groups, because then this will all be working on a list of groups, not of items. For example, in a "grouping together things" rule, where "things" is such a broad description that it can apply to multiple kinds of thing all appearing in the list, the list-maker is likely to set "listing group size" to the number of groups. If the list contains five men and six women, for example, "listing group size" might be 2 rather than 11.
2. The default behaviour. The items grouped together are printed in an English phrase, such as "egg, chicken and farmer". In particular, they are not split onto separate lines even if the rest of the list is. (See previous section.)
3. Examples. (a) Here are Scrabble pieces which are described as "the tile W from a Scrabble set" or similar outside of lists, but which, when they turn up together in lists, are rolled together into "the tiles A, B and D from a Scrabble set".
(b) Maybe we only want an abbreviated form when there are five or more tiles in one place:
(c) We can throw out all pretence at listing and say whatever we like, in fact:
1. When it happens. When Inform prints a text marked with a response letter (A), (B), (C), …, in a rule making use of them. For example, in this rule:
Or, less directly,
2. The default behaviour. To print the current textual value of the response, making any substitutions in the ordinary way.
3. Examples. This activity is not the best way to amend responses or make them dynamic; the whole idea of responses is that they can be changed just as if they were text variables. This activity should be used only if it's important to amend blocks of responses in some systematic way.
(a) With that said, some interesting effects can be achieved. This is a way to see which responses are being printed, for example:
whence:
(b) And this intercepts the activity in order to re-run it in each of the six viewpoints. (Note the way a variable is used to prevent the rule from applying to all of those re-runs as well.)
With that in place,
1. When it happens. When an item is listed in the miscellaneous collection of items present in a room (the ones which do not deserve their own paragraphs): this is normally the last paragraph of a room description.
2. The default behaviour. A bracketed piece of extra information is added for certain items such as containers:
The " (empty)" (note initial space) was added by this activity. (Note that this activity is not responsible for describing further items visible because of the item in question: that is, it does not print the text such as "(in which is a notepad)" which would appear if there were contents. If we want to remove such text, we should use "omit contents in listing": see the activity "for printing the name of something".)
3. Examples. (a) To get rid of such addenda entirely, try:
(b) To add a new form of addendum:
If both examples (a) and (b) are in place at once, we might now read:
1. When it happens. When an item is listed in an inventory of items carried by the player.
2. The default behaviour. A bracketed piece of extra information is added for certain items such as containers:
The " (providing light)" (note initial space) was added by this activity.
3. Examples. (a) To get rid of such addenda entirely, try:
(b) To add a new form of addendum:
1. When it happens. When an action which requires light is tried, and the visibility rules decide that not enough light is present.
2. The default behaviour. To print "It is pitch dark, and you can't see a thing."
3. Examples. (a) This might do for some twilit, penumbral room:
1. When it happens. Inform frequently calculates to see if the player is in light or darkness: this activity happens on the change from light to darkness.
2. The default behaviour. To print "It is now pitch dark in here!".
3. Examples. (a) The most obvious use is to change the text:
(b) But we could also use this activity for sneakier purposes, silently moving things around:
(c) A special description for occasions when the player has climbed into a container and shut it (so that the darkness is the result of his own actions, rather than some external circumstance):
1. When it happens. Inform frequently calculates to see if the player is in light or darkness: this activity happens on the change from darkness to light.
2. The default behaviour. To try the looking action, which usually prints up a room description.
3. Examples. (a) Perhaps the player is initially too disoriented to look around in any coherent way:
1. When it happens. When looking in darkness, or writing the (default) status line in darkness.
2. The default behaviour. To print "Darkness".
3. Examples. (a) One might modify the darkness with some adjective:
(Note that this activity does not come in different forms for different dark rooms: the wording is fixed at "printing the name of a dark room", and we are not allowed to substitute particular dark rooms or assign a "(called …)" onto the mention of the dark room.)
1. When it happens. When looking in darkness.
2. The default behaviour. To print "It is pitch dark, and you can't see a thing."
3. Examples. (a) A simple variation of wording:
(b) More stylishly,
which produces, for instance,
(Note that this activity does not come in different forms for different dark rooms: the wording is fixed at "printing the description of a dark room", and we are not allowed to substitute particular dark rooms or assign a "(called …)" onto the mention of the dark room.)
1. When it happens. Just before input is accepted from the keyboard, Inform constructs a "status line" at the top of the window which is normally displayed in reverse colours (white on black instead of black on white, say).
2. The default behaviour. Makes the status line up out of two pieces, the "left hand status line" and the "right hand status line". Since these can freely be changed, note that the status line is already very customisable without using rules applied to this activity.
3. Examples. (a) The most useful thing about this activity is that it allows us to vary descriptions in the status line. This is especially helpful to abbreviate unduly long room names, which might not otherwise fit:
(b) Again, it's usually not necessary to apply activity rules to this, but occasionally amusing effects are possible if we do:
1. When it happens. Just before writing a paragraph about some item in a room description.
2. The default behaviour. Is to do nothing. However, if a rule is supplied which prints something up, then this replaces the paragraph which would otherwise have been printed. Moreover, any items whose names are said in the course of this rule – for instance, by being listed – are then excluded from the remainder of the room description, because they are considered as having been described sufficiently already.
Warning: because we often want a "for" rule for this activity to make some calculation and then possibly choose to do nothing (see the example "Otranto"), Inform suppresses the usual paragraph not when a "for" rule took effect but when it detected a paragraph having been printed. This can get confused if a text substitution affecting paragraph breaks, say "[line break]", is within the final "say" of a "for writing a paragraph about" rule.
3. Examples. (a) This is a neat way to wrap several things together into the same paragraph:
because now "Mr Wickham looks speculatively at Velma and Daphne" will now prevent the appearance of the subsequent text "You can also see Velma and Daphne."
Inform keeps track of which objects have already been named with an either/or property called "mentioned", which it assigns whenever the name of an object has been automatically printed. So in this case, Velma and Daphne are now mentioned. Note "automatically printed", though: if the text printed had just been "Mr Wickham looks speculatively at Velma and Daphne", rather than the text-substitution list used above, then Inform would not know that Velma and Daphne have been described.
If we ever need to override this – say, we want to list all the women but make sure that Velma gets another paragraph anyway – we could change Velma to unmentioned again after the listing.
1. When it happens. This activity prints up the also-ran paragraph at the end of a room description. These are nondescript items because they don't merit paragraphs of their own: if, as sometimes happens, there are none in the room, then no such paragraph is printed and this activity does not happen. (So to add a further paragraph to a room description, a simpler "after looking" rule should be used, not an "after listing nondescript items" rule.)
2. The default behaviour. The paragraph ordinarily reads as "You can also see a cask and a clock." or similar. Before the activity begins, those objects which are nondescript – in this case the cask and the clock – are given the property of being "marked for listing".
If it turns out that nothing is marked for listing, because of before rules like the one in the example below, then nothing is printed and the activity is abandoned, so that the rules for and after are never reached.
3. Examples. (a) Promoting something out of the nondescript category, by unmarking it.
(b) Changing the normal phrasing of the paragraph. Note that we can also change the listing style; the one below is the default.
1. When it happens. A "locale description" is Inform jargon for the part of a room description which catalogues the visible items in the room. When looking, Inform will normally print the description of the room itself, followed by a locale description for the room. But if the player is in a cage in the room, there will be two locale descriptions: one for the room, then another for the cage. This activity is used to write the locale description for a single domain, and the "something" can be either a room, an enterable container, or an enterable supporter.
2. The default behaviour. Is quite complicated, and is written up in full in the typeset form of the Standard Rules downloadable from the Inform website. Briefly, though: we first run the "choosing notable locale objects" activity to find out what ought to be mentioned here. That assembles a list of things to mention, sorted into priority order. Items with priority 1 go first, then those with priority 2, and so on. The "printing a locale paragraph" activity is run for each, and in practice that usually hands the job over to "writing a paragraph about". Sometimes a paragraph will indeed be written, but not always. Sometimes there is nothing interesting to say, and an item is left until a final, single paragraph which gathers up the leftovers ("You can also see a scarlet fish, a harmonium and a kite here."), the printing of which is done by the "listing nondescript items of" activity. As soon as any item picks up the either/or property "mentioned", by having its name printed, it is struck out so that it will not appear subsequently, whatever its priority.
3. Examples. As general advice: if the effect wanted can be got using "writing a paragraph about" and "listing nondescript items of" alone, use those; if it's necessary to meddle further, use "choosing notable locale objects" and "printing a locale paragraph" to alter the normal processes; use the all-powerful "printing the locale description" activity only when the whole process needs to be altered, not the item-by-item workings.
(a) In the Very Misty Moorlands, nothing on the ground can ordinarily be seen through the swirling mist, so the locale description is suppressed entirely:
(b) Here we take the chance to insert an additional paragraph into the locale description. This does relate to an item which might be described later, but where the player doesn't know that:
1. When it happens. See "printing the locale description". This activity is expected to decide which items ought to be mentioned in a locale description for a given room, enterable container or enterable supporter, and to give each item a priority, which is a number ranging upwards from 1 (which is the top priority). The lower the priority number, the earlier the mention, or at least, the earlier the opportunity to be mentioned: it's up to other activities whether to give it a paragraph of its own or not. This activity only makes something a candidate, and decides what order the candidates will be tried in.
2. The default behaviour. By default, this activity contains only the "standard notable locale objects rule". This chooses exactly those items directly contained by the locale, assigning all of them priority 5. Note that this includes scenery, and other probably unwanted items – those will be excluded later.
3. Examples. (a) In the Misty Moorlands, only large items on the ground are visible through the mist:
Note the special phrase
which should be used only in rules for locale activities. It makes the given item a candidate and sets its priority. (Setting the priority to 0 forces an item not to be a candidate, and can thus undo the effect of previous rules.)
It's best to avoid situations where an item has a locale priority which is higher than that of something it is on top of, or inside, since this can result in an oddly-worded description.
1. When it happens. See "printing the locale description". By this point, the locale description process has identified a number of items as candidates to be described, and worked out a priority order. This activity is then called for each candidate in turn, starting with the highest priority items and working downwards. It can either print some text or not, and can either mark the item as "mentioned" or not: if it does, then the item won't appear subsequently in the locale description. If the activity does nothing, the item becomes "nondescript" and falls through into the final "You can also see…" paragraph, unless another rule mentions it in the mean time.
2. The default behaviour. Is provided by a sequence of seven rules:
3. Examples. If all that's required is to supply an interesting paragraph of room description about something then it's always better to use the "writing a paragraph about" activity, not this one. This activity should only be used when the mechanism itself needs to be adjusted.
(a) The following excludes doors from room descriptions:
(It's usually a good idea to "continue the activity" at the end of rules for this activity, since usually they all need to take effect for a happy outcome to the process. Here it doesn't really matter, since we were trying to stop anything from happening about the door, but it doesn't do any harm either.)
(b) Here's how to abolish what may be the most contentious rule in the whole Standard Rules:
1. When it happens. "Scope" is a term of art in interactive fiction programming: it means the collection of things which can be interacted with at any given moment, which depends on who you are and where you are. Commands typed by the player will only be allowed to go forward into actions if the things they refer to are "in scope". Inform also needs to determine scope at other times, too: for instance, when deciding whether a rule conditional on being "in the presence of" something is valid. It is a bad idea to say anything during this activity.
2. The default behaviour. Is complicated: see the Inform Designer's Manual, 4th edition, page 227. Briefly, the scope for someone consists of everything in the same place as them, unless it is dark.
3. Examples. (a) We very rarely want to forbid the player to refer to things close at hand, but often want to allow references to distant ones. For instance, a mirage of something which is not present at all:
Two different phrases enable us to place unusual items in scope:
This phrase should only be used in rules for the "deciding the scope of…" activity. It places the given object in scope, making it accessible to the player's commands, regardless of where it is in the model world. Examples:
Ordinarily if something is placed in scope, then so are its parts and (in the case of a supporter or a transparent or open container) its contents; using the "but not its contents" option we can place just the box itself in scope.
This phrase should only be used in rules for the "deciding the scope of…" activity. It places the things inside or on top of the given object in scope, making them accessible to the player's commands, but it does nothing to place the object itself in scope. (It might of course be in scope anyway, and if it is then this phrase won't remove it.) Example:
Note that the object in question can be a room, as in this second example.
(b) Another useful device is to be able to see, but not touch, another room:
(This must, however, also be a mirage, as at time of writing Mr Depp is alive and as well as can be expected following the reviews of "Charlie and the Chocolate Factory".) Note that "place the Ballroom in scope" doesn't just allow the player to talk about the dancers, the chamber musicians and so forth, also allows, say, "EXAMINE BALLROOM". To get one but not the other, use "place the contents of the Ballroom in scope" or "place the Ballroom in scope, but not its contents".
(c) In darkness, the scope of someone is ordinarily restricted to his or her possessions (and body), but we can override that:
4. A note about actions. This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types "TAKE SHOEBOX", this activity would happen when SHOEBOX is being examined for meaning. Inform knows the action it would be taking if the current line of command grammar were to be accepted, but it does not yet know to what objects that command would be applied. That means attaching a proviso like "… while taking a container" to a rule for this activity will cause the rule to have no effect – whereas "… while taking" would be fine.
1. When it happens. When the player has typed an ambiguous noun reference, and Inform has made a decision about what was meant, and it matters what this decision is. (If the decision is between three identical gold coins, say, then it doesn't matter, and this activity does not take place.) There are a couple of limitations on this: the activity applies only to the first noun, and only if it's an object. So for a command like SELECT BLUE, where BLUE is a noun referring to a colour value, say, this activity isn't used. But the simple case where the activity does play a part is nevertheless very useful.
2. The default behaviour. Text in brackets such as "(the laminated mahogany box)" is printed, on its own line.
3. Examples. (a) In the following, asking to TAKE TOWER results in the parser choosing the souvenir model (because of the "does the player mean…" rule making the alternative unlikely), and then explaining itself by saying "(The little one, obviously.)" instead of "(the souvenir model Eiffel Tower)".
4. A note about actions. This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types "TAKE SHOEBOX", this activity would happen when SHOEBOX is being examined for meaning. Inform knows that the action will be taking, but nothing else. That means attaching a proviso like "… while taking a container" to a rule for this activity will cause the rule to have no effect – whereas "… while taking" would be fine.
1. When it happens. When the player has typed an ambiguous noun reference, and Inform has not been able to decide what was meant.
2. The default behaviour. A question such as "Which do you mean, the laminated mahogany box or the boom box?" is printed. (This activity shapes the question: it is not responsible for parsing the answer. It would be very mysterious to write rules for this activity such that nothing is printed, because the player would then have no idea what to type.)
3. Examples. The question is harder to print than may first appear, since one must not simply list the options, but also take into account collections of plural objects ("Which do you mean, the gold-tipped pen or a gold coin?"). It is probably better not to try to rewrite this.
(a) But we can place notes before or after: here is a verbose explanation for beginners to IF.
(b) We can also use this activity as a context for other activities. For instance:
causes TAKE TOWER (for instance) to produce a nice tidy question in reply: "Which do you mean, the actual Tower or the souvenir?"
4. A note about actions. This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types "TAKE SHOEBOX", this activity would happen when SHOEBOX is being examined for meaning. Inform knows that the action will be taking, but nothing else. That means attaching a proviso like "… while taking a container" to a rule for this activity will cause the rule to have no effect – whereas "… while taking" would be fine.
1. When it happens. (Two different activities here, but identical except for applying to different nouns.) This happens when an Understand sentence fails to supply a noun for an action which requires one. For example, in the sentence 'Understand "seize" as taking.' – the "taking" action is incompletely specified, because it requires a noun, and there's no noun in the command to be understood.
Note that this is not what happens if it's the player who fails to supply the noun. That is, suppose the player types a half-finished command like TAKE, which can't be matched against (for example) 'Understand "take [things]" as taking.' because the player didn't name any thing(s). Typically a story will reply to such a command with a question asking for clarification, but sometimes it makes guesses about what was meant. The "supplying a missing noun" activity plays no part in this guesswork, and can't influence it: that's the task of the "does the player mean" rulebook.
Suppose we do have the first of these cases, then. "Supplying a missing noun" takes place to remedy the problem. It can either:
(i) Set a noun, printing text like "(presumably the black bag)" if it wants, in which case the action goes forward, though it is still subject to the full rules on accessibility exactly as any other action would be; or
(ii) Make no choice, in which case no action takes place and the player's command is rejected. If the activity printed nothing, Inform will produce a generic reply to the player that "You must supply a noun.".
2. The default behaviour. In the default grammar for Inform, only three such half-finished actions are ever Understood. One is "going" with no direction, for which this activity simply prints a refusal. The other two are the two undirected senses, "smelling" and "listening". In each case, the "supplying a missing noun" activity sets the noun to the current location: so, for instance, typing the bare command "listen" might generate the action "listening to the Shoreline".
3. Examples. (a) This is the definition Inform uses to make "listen" work as outlined above:
(b) It can be elegant to allow second nouns to be dropped with habitual actions, or where the choice is obvious:
Note that, in order for our activity to succeed, we do need to supply a grammar line allowing the player to try "unlocking it with" using only one noun. Otherwise, the command "unlock something" will still produce the question "What do you want to unlock the door with?"
1. When it happens. When reading a command from the keyboard.
2. The default behaviour. Print the prompt text; wait for the player to type something and press return. Reject an entirely blank line, and treat a command beginning "oops" as a correction to the previous one. This is a fairly complicated business, so it is probably best not to change the "for" rules for this activity: "before", and especially "after", are another matter. (Note, however, that if Inform does reject a blank line and ask for another then this all happens inside the "for" rules: no "after" occurs after the blank line, nor does a "before" happen before the second attempt by the player. It is all a single round of the activity, not two.)
3. Examples. (a) To lead absolute beginners in gently:
(b) The following responds politely but firmly if the player tries to type "please look", say, instead of just "look":
To explain. Fragments of what the player has typed are called snippets: "the player's command" is the entire thing. We can test if a snippet matches a given pattern like so:
This condition is true if the given snippet exactly matches the specification. Example:
will be true if the command is ROOM 101, but not if it's EXPLORE ROOM 7.
This condition is true if the given snippet does not exactly match the specification.
This condition is true if the given snippet includes words matching the specification, either at the beginning, in the middle, or at the end. Example:
will be true if the command is ROOM 101, EXPLORE ROOM 7, or ROOM 22 AHOY, but not if it's VISIT ROOM GAMMA 7.
This condition is true if the given snippet does not include any run of words which matches the specification.
Lastly, we took drastic action with another new phrase:
This phrase should be used only in rules for the "reading a command" activity. It tells Inform not to bother analysing the text further, but to go back to the keyboard. (No time passes; no turn elapses; nothing happens in the simulated world.)
(c) An improved version takes commands like "please drop the coin" and strips "please" from them, but then allows them to proceed normally:
"Matched text" is a snippet containing the words which matched against the pattern in the most recent "includes" condition, so in this case it contains just the single word "please". Two phrases allow snippets to be altered:
This phrase should be used only in "after" rules for the "reading a command" activity; it replaces the snippet of command, usually the "matched text" found immediately before, with the given text. Example:
This phrase should be used only in "after" rules for the "reading a command" activity; it removes the snippet of command. Example:
Note that "replace" and "cut" can only be used in "after reading a command" rules: not when an action has been chosen and has gone ahead into its rulebooks. Once the "reading a command" activity has finished, the command is final.
(d) To make the word "grab" an abbreviation for "take all":
("Snippet" is actually a kind of value, so we could say "Ah, you typed '[the player's command]'!" or some such if we liked. But in practice only three snippets are likely to be useful: the two mentioned above, "player's command" and "matched text", and the "topic understood", used when matching the "[text]" token in command grammar.)
(e) Finally, we can make still more detailed alterations to the text of the command using the techniques presented in the Advanced Text chapter. For instance:
This phrase should be used only in "after" rules for the "reading a command" activity; it replaces the current command text entirely. Example:
This converts the player's command to text, which is then manipulated by searching for any punctuation mark and replacing it with blank text (that is, deleted), and then put back again as the new command.
1. When it happens. When an action is tried which requires the actor (normally the player, of course) to be carrying something, but which is not in fact carried by that person. For instance, if the player types WEAR OVERCOAT in reference to a Moroccan overcoat currently draped over a chair.
2. The default behaviour. To print text such as "(first taking the Moroccan overcoat)" and then silently try taking the object in question (the overcoat). If the take succeeds, the silence means that nothing else is printed: if it fails, it will say why.
No matter what rules are written for this activity, it is impossible to use it to allow the action to go ahead even without the item. The activity allows us to change how, or if, an implicit take will happen, but not to change the consequences of failure. (To do that, we would need to say that "The carrying requirements rule does nothing", but this kind of unstitching of the action machinery needs to be done with caution.)
3. Examples. (a) Forbidding implicit takes for certain dangerous items. (This seems especially fair if taking such items might cause death: the player will not wish to be killed on the strength only of our guess as to what he might be intending to do.)
(b) Changing the way the implicit action is reported for the player:
(c) Combining implicit takes when the noun and second noun must both be carried:
(d) Making another character reply amusingly:
(e) Causing implicit takes which wouldn't otherwise happen. Suppose we have a photographing action, and there are very small flowers which can't conveniently be snapped without being first picked. We then want an implicit take to occur, even though we wouldn't want this for other sorts of photography. So:
Note that if the activity doesn't succeed in taking the item, it's expected to print some text explaining this, which is why we don't need to say anything further.
1. When it happens. The parser is the part of the run-time software, included in all works produced by Inform, which tries to match the player's command against the grammar provided by the work. When it is unable to make a valid match, the parser prints an error to the player: for instance,
There are more than twenty possible messages. The one which the parser wants to say is stored in the variable "latest parser error", which has the convenient kind "command parser error". This has the following possible values:
2. The default behaviour. Prints the message in question.
3. Examples. (a) Perhaps for newcomers:
(b) Or to give the parser a certain amount of character:
(c) This can be helpful for seeing what's going on:
1. When it happens. When parsing a command such as "take all", where the player uses "all" to signify everything within reach.
2. The default behaviour. The actual method used is complicated, as "all" is not as simple as it seems – "take all" would not include the player's own body, for instance, or the crescent moon. The point of this activity is to allow the normal method to be changed for given objects, or given kinds of object.
3. Examples. (a) Removing scenery from "all" (but see (4) below):
The phrases "it does" and "it does not" make a decision.
(b) Ensuring that a given thing, which might otherwise be excluded, is included:
4. The Standard Rules already uses this. Note that the Standard Rules already stocks this activity with several rules:
5. A note about actions. This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types "TAKE SHOEBOX", this activity would happen when SHOEBOX is being examined for meaning. Inform knows that the action will be taking, but nothing else. That means attaching a proviso like "… while taking a container" to a rule for this activity will cause the rule to have no effect – whereas "… while taking" would be fine.
1. When it happens. The banner is the bibliographic masthead text, which typically looks something like this:
(The serial and build numbers are those applying when the story file was last made: these ones are from the mid-2000s.) The banner is printed at the start of play, and when the player types "version" at the command line, and when say "[banner text]" occurs.
This text substitution expands to the banner text giving bibliographic details of the current story file, rather like the opening credits of a movie, or the title page of a book.
2. The default behaviour. Prints the text above, giving the title, the headline, the author, the release number, the date of compilation (that's the serial number: YYMMDD), and version numbers of the Inform components used to put the story together.
3. Examples. (a) Adding a line to the banner:
(b) Simplifying the banner:
1. When it happens. The obituary is the text "*** You have died ***" or similar, sometimes followed by a final score, if the appropriate use option ("Use scoring.") is in force.
2. The default behaviour. Printing the aforementioned text, then the final score, and reducing the status line to a largely blank state.
3. Examples. Here's one way to add to the verdict of history:
1. When it happens. When the player chooses "AMUSING" from the short menu of choices after a story has been won. Traditionally, this is where the author gets to point out quirky by-ways of the story, or make some final acknowledgements, or simply salute the player's perseverance. Note that the AMUSING option is only offered when the story has ended finally, and that it is only offered if there is at least one rule present in the "for amusing a victorious player" rulebook.
2. The default behaviour. None. The "for amusing a victorious player" rulebook is empty by default, and no amusement is available.
3. Examples. The format would be like so:
1. When it happens. This activity is provided solely as a "hook" for any low-level tasks which need to be performed when the virtual computer which runs Inform story files is starting up. This happens much earlier than "when play begins" rules, and should be used only as a last resort.
It should be remembered that Inform can produce story files for several different virtual computers. On some of these, it will not be safe to print any text during this activity, as the windows which would display such text do not yet exist.
2. The default behaviour. None.
3. Examples. No detailed examples will be given here, but the activity might be used (for instance) to set styles for the Glulx windows shortly to be brought into existence.
When we open the casing and look inside the machinery of Inform, what we see are rules and rulebooks. We seldom need to know how this machinery works, but every once in a while we want to replace components, or even install new mechanisms of our own. And as we shall see, creating new rulebooks can be a neat way to tackle complicated simulations full of exceptions and special cases.
So far we have seen many rules, and the term "rulebook" has frequently but vaguely been used. Here is a summary of the rulebooks seen so far:
Which makes around 340 rulebooks before we even start to write. All the same, not everything in Inform belongs to a rulebook – timed events, for example, are rules which normally live outside of rulebooks; and other constructions, such as newly-created phrases, or definitions, may look vaguely like rules, but they aren't. So the following are not rulebooks:
Most of the rules built into Inform have names. For instance, a rule called "the advance time rule" is the one which increments the number of turns and advances the clock, values which are usually not visible, but are ticking away behind the scenes.
A rulebook is a list of rules to be followed in sequence until one of them makes a decision. For instance, when actions get to the "instead" stage, each "instead" rule is tried until one of them chooses to do something. If the source text contains the rules
and a command to TAKE something is tried, then only one of these rules will have any effect. The "instead" rulebook contains:
Inside their rulebook, the rules are not listed in the order of definition in the source text. Rule (1) comes before rule (2) because it applies in more specific circumstances. This is the main idea: a rulebook gathers together rules about making some decision, or taking some action, and sorts them in order to give the more specific rules first choice about whether they want to intervene.
Whereas only some rules are named (the two "instead" rules above have no name, for instance), every rulebook has a name. For convenience, the following forms of rule and rulebook name are synonymous:
The names of built-in rules have been chosen as descriptively as possible: the "can't go through closed doors rule", for instance. Names for rules tend to be verbose, but this is a situation where clarity is very much better than brevity.
Stretching a point seasonally, we might write:
This rule is nameless. It needs no name because it will never need to be referred to: by identifying it as an every turn rule we have already said enough to lodge it in the "every turn" rulebook. In fact, though, it is easy to create a named rule:
The name of a rule must always end with the word "rule", for clarity's sake. (The phrasing "This is the … rule" is used because "The … rule" would be open to misinterpretation.)
Previously we had a rule which had no name, but belonged to a rulebook: now we have the opposite, because although the "blossom shaking rule" has a name, it has not been placed in any rulebook. That means it will probably never be applied, unless we give specific instructions for that.
Alternatively, it is possible to both name and place a rule in a single sentence:
Now the "alternative blossom rule" is a named rule in the "every turn" rulebook.
If rules can manage perfectly well without, why bother to have names for rules?
The answer is that although Inform contains an elaborate mechanism for placing rules into the correct rulebook at the correct position, and this happens automatically, Inform will sometimes get it wrong. It will use a rule we do not want, or place them in an order which does not suit us. To put this right, we can give explicit instructions which take precedence over Inform's normal practice. This is done with the "to list" verb, as in the following examples.
1. The simplest usage is to place a named rule, which currently has no home, in any rulebook of our choice. (This looks redundant, but just occasionally we want the same rule to appear in two different rulebooks.)
A rule can appear in more than one rulebook, but within any single rulebook it can only appear once.
2. We can also specify that the rule needs to appear before, or after, some other named rule in the same rulebook:
Instead of being placed in specificity order in the whole "instead" rulebook, the "collapsing bridge" rule would now be placed in specificity order only in the first half of the "instead" rulebook – the rules from the start up to (but not including) the "moving doorways" rule. To reiterate: that doesn't necessarily mean it will be immediately before the "moving doorways" rule; it will be placed according to Inform's usual sorting rules within that range.
"Listed" sentences are obeyed by Inform in sequence, so if later ones issue instructions contradicting earlier ones, it's the later ones which win out. Thus if we say "A is listed before B in X" and then "B is listed before A in X", the result is that B comes before A.
3. We can specify that a rule needs to appear first or last in a given rulebook:
Again, if we make several such instructions about the same rulebook then the most recent one wins: "A is listed first in X. B is listed first in X. C is listed first in X." causes rulebook X to begin C, B, A.
4. We can also substitute one rule for another:
If rule A is listed instead of rule B in rulebook X, and A was already a rule in rulebook X, then A will move from its previous position to occupy the place where B was, and B will disappear. (In particular rule A will not be duplicated, which would break the principle that no rule occurs twice in the same rulebook.)
5. And we can strike down existing rules, either specifically or in all their applications:
This does not actually destroy the rules in question: they could still, for instance, be put into another rulebook, or even be applied explicitly, as we shall see. But unless we take deliberate action to the contrary, un-listing a rule amounts to abolishing it forever. This is a little drastic, and more subtle effects can be seen in the next section.
Here is another way to abolish an already-existing rule:
The rule continues to be listed in any rulebook it would normally be listed in: but now it doesn't do anything. More usefully, we can attach a condition:
or:
We can also substitute a rule of our own:
and once again a condition can be applied:
The Rules page of the index for a project offers a view of the rulebooks and their contents, with two major exceptions: built-in rules for specific actions are left to the Actions page, and any rules for scene endings or beginnings are left to the Scenes page.
As we have seen, we need to know the name of a rule before we can change its rulebook listing or alter its applicability. The Rules and Actions index pages show the names of the built-in rules, which are not worth memorising. (Typing can be saved by using the paste-into-source buttons, or by selecting a rule's name and copying and pasting it by hand.)
In the Rules index, each rulebook is named and then followed by a list of the rules within it, one on each line: if nothing follows, then the rulebook is currently empty. The rules are given in order, and icons are used which indicate which rules are more specific than which others. Hovering the mouse over such an icon should bring up a "tooltip" which explains Inform's reasoning.
As this suggests, Inform performs its automatic sorting using a precise collection of Laws (the term "rules" would be ambiguous here, so we call these guidelines Laws instead), and the tooltip shows which Law was applied. It is bad style to write source text which absolutely depends on detailed points of these Laws, but they are documented at the end of this chapter for those who do wish to see the full details.
In general, a rule looks like this:
though in a few common cases (where the preamble begins with Before, After, Instead of, Every turn, or When, and there is only one phrase in the list) the colon can be replaced with a comma. Three kinds of declaration are special, and these we can tell apart by the first word:
All other declarations (that is, starting with any other word) create rules fit for going into rulebooks. The preamble can either just be a name, which is required to end with the word "rule", or it can give circumstances and have no name, or it can do both:
The circumstances should be a sequence of the following ingredients, each of which is optional except the name of the rulebook:
The word "first" or "last", if present, is significant: it tells Inform exactly where the new rule should be placed into its rulebook, and so overrides the normal practice of placing the rule according to how specific it is.
On the other hand, the use of any of the following:
is purely to make the text easier to read: Inform does not make any direct use of these words (except perhaps that it may help to avoid ambiguities by separating the rulebook name from what is being applied to). Thus in the rule
the word "instead" is the rulebook's name, while "of" is technically optional. "Instead rule about kissing Clark: …" would work just as well.
In this whole list of possible ingredients, only the rulebook name is compulsory. We could define a rule called simply "Instead: …" if we wanted – though its universal applicability would make it pretty disruptive, with every action stopped in its tracks.
Creating a new rulebook is also straightforward, as we see in the following modest example story:
The creation of the rulebook is all very well, but without the final sentence it would never be used. The crucial new phrase here is:
This phrase causes the rule to be obeyed immediately (rather than simply at predetermined times such as when a particular action is being tried, or at the end of every turn, and such). Example:
Like "number" or "text", "rule" and "rulebook" are kinds of value built into Inform: "the blossom rule" is a value whose kind is "rule", whereas "the every turn rules" is a value whose kind is "rulebook". In fact, Inform considers a rulebook to be a special case of a rule, so that whenever a rule is required it is legal to name a rulebook instead, but not vice versa. The "follow" phrase here…
…expects to be applied to a value of kind "rule"; "the appraisal rules" is in fact a rulebook, but since that counts as a rule the phrase makes sense to Inform. To follow a rulebook means to run through all its rules in turn, stopping when one rule reaches an outcome; to follow a single rule means just that one, of course.
When created, a rulebook starts out with no rules in it – in this example, of course, we quickly defined a couple of rules to go into it. But it's often the case in Inform that a rulebook exists without ever being stocked up, especially if the rulebook is for some obscure purpose never needed. The built-in adjectives "empty" and "non-empty", applied to a rulebook, test whether any rule is present or not.
Every rulebook works on a value supplied to it, though it doesn't always look that way. The kind of the value is called its "basis"; for example, if a rulebook works on a number, it's called a "number based rulebook". Most of the rulebooks seen up to now have been action based rulebooks:
"Instead" is an action based rulebook, and the action it works on is the one currently being processed. Besides before, after and instead, other action based rulebooks include the check, carry out, and report rules; general rulebooks such as every turn rules, the visibility rules, the turn sequence rules; and rules specially for dealing with the actions of other characters, such as the persuasion and unsuccessful attempt rules. But we have also seen object based rulebooks:
"Reaching inside" is an object based rulebook, and here we're giving it a rule which applies if the object is the flask. Inform would reject something like:
because 100 has the wrong kind to fit – it's a number, not an object. There are many object based rulebooks, because most activities built-in to Inform act on objects. For example, the "printing the name of" activity has three rulebooks attached to it: before printing the name of, for printing the name of, after printing the name of. All of these are object based rulebooks.
Finally, we've also seen scene based rulebooks (which is how rules like "when a recurring scene ends" worked, in the Scenes chapter).
If a rulebook is declared like so:
then it is an action based rulebook. If we want something different, we must write something like this:
which produces:
Here we needed a variation on "follow" which supplies the value to apply to:
This phrase causes the rule to be obeyed immediately (rather than simply at predetermined times such as when a particular action is being tried, or at the end of every turn, and such), and applies it to the value given, which must be of a matching kind. Example:
And here is an example based on objects:
And we might use the flotation rules in a circumstance like this:
When a rulebook is intended to perform some complicated task or calculation, it is sometimes useful for earlier rules to be able to leave information which will help later ones.
For instance, suppose we want a rulebook which is intended to print out the player's current aptitude. We will suppose that this is a number from 0 upwards: the higher, the apter. The player gets bonus aptitude marks for achievements, but marks deducted for accidents, and so on. Moreover, we want to design this system so that it's easy to add further rules. The natural solution is to have a number which varies (or 'variable') acting as the running aptitude total: it should start at 0 and be altered up or down by subsequent rules. First, we should make the rulebook, and then add a variable:
The new value 'aptitude mark' is shared by the rules of the rulebook: nobody else can see it. It is created at the start of the rulebook being followed, and destroyed at the end. (If the rulebook should be followed a second time inside of itself, a new copy is created which does not disturb the old one.) So, in this case, 'aptitude mark' is started as 0 (since it is a number) each time the aptitude rules run. We can then write whatever rules we please to modify it:
And we had better do something with the result:
A rulebook can have any number of variables like this. They behave much like "let" values except that they last for a whole rulebook, not an individual rule or To phrase definition. (Well, strictly speaking they are accessible not just to the rules which belong to the rulebook, but also to any rules which previously belonged to the rulebook but were kicked out by means of an explicit rule-listing sentence. This is good because otherwise they will suddenly cause problem messages when unlisted.)
Though we have blurred over this point so far, each rule must ordinarily end with one of three outcomes: success, failure and neither ("no outcome").
When a rulebook is followed, what happens is that each of its rules is followed in turn until one of them ends in success or failure – if ever: it is possible that each rule is tried and each ends with no outcome, so that the rulebook simply runs out of rules to try.
For some rulebooks, these are not useful ideas: "every turn" rules, for instance, by default never produce an outcome, which is why the "every turn" rulebook normally runs through all its rules at the end of each turn. (Use of the phrases below can change that, so it's best not to use them in "every turn" rules.) But for other rulebooks, such as "check taking", it's important that a rule which fails will stop the whole rulebook. For instance, we might find that the "can't take yourself rule" produces no outcome (because we aren't trying to do that), and then likewise the "can't take other people rule" (ditto) but that the "can't take component parts rule" prints up a complaint, and fails the action: the rulebook stops, and never goes on to (for instance) the "can't take scenery rule". This is good, because an impossible action often fails for several reasons at once, and we only want to print up one objection, not a whole list.
To follow the working of this mechanism, we need to be able to predict the outcome of any given rule. Sometimes this is easy to spot. For instance, in a rule which works on actions:
("Success" and "failure" are technical terms here: they do not mean that the player has or hasn't got what he wanted.) This is why the rule:
ends in failure, and therefore stops the "before" rulebook. Another easy-to-spot case is when a rule makes use of the explicit phrases:
This causes the current rule to end immediately, with its outcome considered to be a success. The rulebook being worked through also ends, and is also a success.
This causes the current rule to end immediately, with its outcome considered to be a failure. The rulebook being worked through also ends, and is also a failure.
This causes the current rule to end immediately, but with no outcome. That means the rulebook being worked through will continue to run on, beginning with the next rule.
But what happens if a rule simply doesn't say whether it succeeds, fails or has no outcome? In that case it depends on the rulebook. For almost all rulebooks, a rule which doesn't make a choice has no outcome, as in the following example:
This rule, if it takes effect, ends with no outcome – so the action continues. But other rulebooks have a different convention: the most important is "instead", where a rule making no explicit choice is deemed to end in failure. For instance:
This rule, if it takes effect, ends in failure and therefore stops the action.
We call this the default outcome of a rulebook. The default outcome of "before" (and of almost all rulebooks, in fact) is no outcome; the default outcome of "instead" is failure; the default outcome of "after" is success. The few exceptional cases with default outcome success or failure are marked as such in the Rules index.
When we create a rulebook, it will default to "no outcome". But we can specify otherwise with sentences like so:
Finally, note that the default outcome for a rulebook is really the default outcome for any rule in that rulebook: if no rules in the rulebook ever apply, for instance if there aren't any and the rulebook is empty, then the rulebook ends with no outcome at all.
We can test the latest outcome like so:
This condition is true if the most recently followed rule or rulebook ended in success. Example:
This condition is true if the most recently followed rule or rulebook ended in failure. Example:
Note that this is not the opposite of "rule succeeded", because there's a third possibility: that it ended with no outcome.
We have seen that the terms "success" and "failure" can be misleading – after all, it might be a good thing for a particular rulebook to "fail". At any rate, these are vague terms, and we don't want to have to remember the conventions used by every rulebook. This is why certain rulebooks have explicitly named outcomes instead. For instance, the "visibility" rules are allowed to have the outcomes:
These look like phrases, but are in fact named outcomes which can only be used in visibility rules. (They would make no sense elsewhere, and Inform will not allow their use if they are clearly out of context.) Such named outcomes are listed in the Rules index.
There can be any number of named outcomes. For instance, the Standard Rules define:
which makes five possible outcomes. Five outcomes seems to contradict the principle that there are only three possible outcomes for a rule: in fact, though, the five are counted as five different forms of "success", and any of them will cause a "does the player mean" rule to succeed. If we do not want this, we can instead specify explicitly how the named outcomes correspond to success, failure or "no outcome":
Again, see the Rules index for examples.
The same named outcome can be used for more than one rulebook, and can have different meanings in the context of different rulebooks – "good news" could be defined as success in one rulebook and failure in another, for instance. (This means that rulebook creators need not worry about name clashes and is an important difference in behaviour between rulebook outcomes and kinds of value.) We can even name a specific named outcome as the default outcome for rules in this rulebook:
After a rulebook using named outcomes has run, we can test which outcome occurred by using the phrase:
This phrase produces the (named) outcome of the phrase most recently followed. Example:
Each named outcome is a value if followed by the word "outcome", which is how "absolute silence" has become "the absolute silence outcome". Named outcomes can be said, so we could use the text substitution "[outcome of the rulebook]", for instance. A final caveat: it is perfectly legal to create a named outcome which means "no outcome", but if so then this will never be "the outcome of the rulebook" because "no outcome" is not an outcome.
We have now seen two ways to write the outcome of a rule: as simple success or failure, with more or less explicit phrases like:
and by using a named outcome for the current rulebook as if it were a phrase, as in:
There is still a third way: we can stop a rule and at the same time produce a value. This isn't needed very often – none of the built-in rulebooks in the Standard Rules produces a value.
As we've seen, every rulebook has one kind of value as its basis, and it also has another kind of value for it to produce. If we call these K and L, then we have altogether four ways to write down the kind of a rulebook:
If we don't mention K, Inform assumes the rulebook is action based. If we don't mention L, Inform assumes L is "nothing", that is, Inform assumes no value is ever produced. Thus
is equivalent to
But let's now look at a rulebook which does produce something.
This rulebook works out which thing the cat will destroy next. We might have rules like this one:
The value is produced only when a rule succeeds, using this phrase:
This phrase can only be used in a rule which produces a value, and the value given must be of the right kind. It causes the current rule to finish immediately, to succeed, and to produce the value given.
How are we to use the cat behavior rulebook? If we write:
then the rulebook runs just as any other rulebook would, but the value produced is lost at the end, which defeats the point. Instead, we might write:
The key phrase here is
which accesses the value this rulebook produces. In general, we write:
This phrase is used to follow the named rule, and to collect the resulting value.
This phrase is used to follow the named rule based on the value given, and to collect the resulting value.
It often happens that one rule needs to invoke another one. Most of the time, the best way to do this is with "follow":
More often, though, we want not only to invoke another rule, but also to be guided by its advice. For this, we use the otherwise identical phrase:
This phrase applies the given rule, and makes its result the result of the present rule. If the rule being abided by succeeds or fails then the original rule also stops, at once and without going on to any further instructions. Example:
This duplicates the effect of a rulebook of four rules: the "omnibus rule" tries each in turn, and stops as soon as any of them stop.
This phrase applies the given rule to the given value, and makes its result the result of the present rule. If the rule being abided by succeeds or fails then the original rule also stops, at once and without going on to any further instructions.
Abide might be used in examples like this one:
Had we used "follow" instead of "abide by", then in the event of the player typing "drop angel" the text "The glass angel is too fragile for such rough handling" would be printed, which is correct – but then the action would continue as though no difficulty had occurred, which is definitely not correct.
Finally, we can "anonymously abide":
This phrase applies the given rule, and makes its result the result of the present rule. If the rule being abided by succeeds or fails then the original rule also stops, at once and without going on to any further instructions. However, the rule deemed to have decided the outcome is the one abided by, not the one doing the abiding.
This is only useful in complicated situations where one rulebook uses another which… and so on. Its effect is exactly the same as "abide", except that the rule deemed to have decided the outcome is the one abided by, not the one doing the abiding. It thus allows a rule or rulebook to act purely as a middle-man, never getting the blame or the credit for what happens. The rule which made the decision is often not very relevant anyway, but it's used as the source of the value "reason the action failed" (see the Advanced Actions chapter).
Rulebooks handle almost all of the important tasks which an Inform work of IF must carry out in order to keep play going. We have seen them used in clarifying the player's command, supplying missing ingredients, processing the action to see what should happen, responding, and so on: by this point in the documentation, it must look as if Inform uses rulebooks for everything.
This is nearly true. There is not actually a super-rulebook controlling everything. (Such a super-rulebook would need to repeat itself and never finish, something a rulebook is not allowed to do.) Instead, what happens during play looks like so:
The command parser occasionally calls on the services of activity rulebooks to help it, but otherwise gets on with its job in ways that we do not "see" as Inform 7 users. The rest of what happens involves rulebooks, and in particular two important beneath-the-surface rulebooks: action processing and turn sequence.
The action processing rules are used whenever an action must be tried, by whoever tries it. This usually happens in response to player commands, but not always: it might happen because of a "try…", and it can certainly interrupt an existing action.
The turn sequence rules are used at the end of each turn, and include housekeeping as well as timekeeping. They consult the "every turn" rulebook, and advance the time of day, among other useful tasks.
In general, we should only modify the operation of these two crucial rulebooks as a last resort. Play can evidently fall to pieces if they cease to work normally.
Large works created by Inform are heaped high with rules, most of them instead rules, but with a leavening of befores and afters as well. What will happen if these conflict with each other? For instance:
Such clashes are resolved by sorting the rulebooks in order of specificity: thus your daughter gets in before your mother-in-law, because although both have rules hanging on the "opening" action, "an open container" is more specific than "a container". The full set of Laws used by Inform to sort rulebooks is quite elaborate. As we've seen, practical consequences can be investigated using the Rules index; and in most cases, the results are either natural (as above) or irrelevant (because the two rules being compared could not both activate at the same time anyway); but the full set of Laws is laid out below, for reference. It is probably a bad idea to write source text which absolutely relies on non-obvious rule sorting conventions, just the same, because this will make the source text harder to read and understand.
Sorting is done by comparing rules in pairs to decide which is more specific. We shall call these rules X and Y. The Laws are tried in sequence; the first Law to distinguish X and Y gets to decide which is more specific. If no Law is able to decide, X and Y go into the rulebook in order of their appearance in the source text – that is, whichever is defined first appears earlier in the rulebook and therefore takes priority.
Law I – Number of aspects constrained. For action-based rulebooks, rules are scored from 0 to 6 according to whether they constrain any of: (i) the exotic "going" clauses (pushing, by and through), (ii) the location of the action (in, from and to), (iii) the things directly involved (actor, noun, second noun, "nowhere" in the case of "going"), (iv) the presence of others (in the presence of…), (v) the time at which the action occurs (when, or "for the nth time" or "for the nth turn"), and/or (vi) the scene the action occurs in (during). For value based rulebooks, rules are scored from 0 to 3 according to whether they constrain: (i) the value parameter, (ii) the scene in which the rulebook is followed (when, during), and/or (iii) any condition which must hold or activities going on at the same time (when/while). A higher score is more specific than a lower one.
Law II – When/while requirement. A rule with a when/while restriction beats one without.
Law III – Action requirement. A rule with a more specific action requirement beats one with a more general action requirement. (Or similarly, for value based rulebooks, a rule with a more specific parameter requirement beats a more general one.) Details are given below.
Law IV – Scene requirement. A rule with a scene restriction ("during") beats one without.
Details of Law III now follow:
Law III.1 – Object To Which Rule Applies. For value based rulebooks only: the more specific value requirement wins.
Law III.2.1 – Action/Where/Going In Exotic Ways. A more specific combination of "…pushing…", "… by …", and "… through …" clauses in a "going" action beats a less specific. (Placing conditions on all three of these clauses beats placing conditions on any two, which beats any one, which beats none at all.) In cases where X and Y each place, let's say, two such conditions, they are considered in the order "…pushing…", "…by…" and then "…through…" until one wins. (The idea here is that pushing something from room to room is rarer than travelling in a vehicle, which in turn is rarer than going through a door. The rarer action goes first, as more specific.)
Law III.2.2 – Action/Where/Room Where Action Takes Place. A more specific combination of conditions on the room in which the action starts, and in which it ends, beats a less specific. For all actions other than "going", there is no combination to be considered, and what we do is to look at the specificity of the "… in …" clause. (So "Before looking in the Taj Mahal" beats "Before looking".)
For "going" actions, there are strictly speaking three possible room clauses: "… in …", "… from …" and "… to …". However, "… in …" and "… from …" cannot both be present, so that in practice a "going" rule constraining two rooms beats a "going" rule constraining only one.
If both the room gone from (the "…in…" or "…from…" room, whichever is given) and the room gone to (the "… to…" room) are constrained, then the constraints are looked at in the order from-room followed by to-room, since an action which goes to room Z could start in many different places and thus is likely to be more general.
Giving a place as a specific room beats giving only the name of a region; if region R is entirely within region S, then a rule applying in R beats a rule applying in S. (Note that regions can only overlap if one is contained in the other, so this does not lead to ambiguity.)
Law III.2.3 – Action/Where/In The Presence Of. A more specific "…in the presence of…" clause beats a less specific one. (This is again a constraint on where the action can take place, but it's now a potentially a constraint which could be passed in many different places at different times, so it's the most likely to be achieved and therefore the last to be considered of the Laws on Where.)
Law III.3.1 – Action/What/Second Thing Acted On. A more specific constraint on the second noun beats a less specific. Thus "putting something in the wooden box" beats "putting something in a container".
Law III.3.2 – Action/What/Thing Acted On. A more specific constraint on the first noun beats a less specific. Thus "taking a container which is on a supporter" beats "taking a container".
In the case of "going" actions, the first noun is a direction. The special constraint "going nowhere" (which means: a direction in which the actor's location has no map connection) is considered more general than any other constraint placed on the first noun, but more specific than having no constraint at all. Thus "Instead of going north" beats "Instead of going nowhere" which beats "Instead of going".
Law III.3.3 – Action/What/Actor Performing Action. A more specific constraint on the actor beats a less specific.
Law III.4.1 – Action/How/What Happens. A more specific set of actions beats a less specific. For instance, "taking" beats "taking or dropping" beats "doing something other than looking" beats "doing something". A named kind of action (such as "behaving badly") is more specific than "doing something", but considered less specific than any explicitly spelled out list of actions.
Law III.5.1 – Action/When/Duration. An action with a constraint on its history ("for the fifth time", say, or "for the fifth turn") beats one without. If both rules place constraints on history, then the one occurring on the smaller number of possible turns wins (thus "for the third to seventh time" – 5 possible turns of applicability – beats "for less than the tenth turn" – 9 possible turns).
Law III.5.2 – Action/When/Circumstances. A more specific condition under "…when…" beats a less specific one. These conditions could potentially be complex: Inform judges how specific they are by counting the clauses found in them. The more clauses, the more specific the condition, it is assumed.
Law III.6.1 – Action/Name/Is This Named. A rule with a name ("the apple blossom rule", say) beats a rule without.
So far, we have dealt with text as something which comes in little packets: we have printed it out, read it in from the keyboard, and compared it with other text. But we have never tried to open the packets and get at the contents, letter by letter, or to make any alterations, or look for certain combinations of letters. These tricks are surprisingly seldom needed – a surprise, that is, given that everything Inform does is textual – but they are in fact open to us. For example:
will be true at, for example, 11:30 PM and 1:22 AM, but not at 3:15 PM. What happens here is that Inform expands the time of day into a text, say "11:30 PM", then extracts the first character, say "1", and tests it.
Until 2012, Inform had two kinds of text – plain "text", and "indexed text" – but there's now only "text", which has all of the abilities of both.
Inform creates "story files" for very small virtual computers (capable of running on phones, for instance) where memory is tight. If we create a number variable and keep on adding 1 to it, the value simply gets bigger. But if we make some text and keep on adding a letter "x" to it, the text takes up more and more space, growing into longer and longer runs of "x"s until there is no more space to hold it.
The following warnings are rather like the tiny print about side-effects on medicine bottles: that is, we mostly ignore them, and if the drugs should kill us, well, at least we have the consolation of knowing we were warned. There are basically three limitations on text:
(1) An amount of memory has to be set aside for text (and other flexible-sized data), and Inform guesses the amount needed. Story files using the Glulx format (see the Settings panel) are able to increase this as necessary in play, so there's no problem if the guess was wrong. But Z-machine story files are stuck with whatever amount of memory was initially chosen.
That choice can be increased with a use option, like so:
Inform raises its estimate of the amount needed to ensure that this amount is always at least its own guess, and also at least any amount declared like this. (And then it rounds up to the nearest power of 2, as it happens.) The default value of "dynamic memory allocation" is 8192. In practice, this use option isn't needed much, though, because any story needing large amounts of dynamic memory will likely be on Glulx in any case.
(2) Text has a maximum length. This maximum is normally 1000 characters, which ought to be plenty, but can be raised by sentences such as:
What happens if this is broken, that is, if we try to use text overrunning this length? The Z-machine may simply crash, so if there is any chance that any single text may grow unpredictably large, Glulx should always be used. On Glulx, overrunning text is truncated safely, except that under Glulx 3.1.0 or better the story file will try to use dynamic memory allocation to expand the limit as needed to avoid truncation. (Testing shows that text is slow to manipulate once it grows beyond about 20,000 characters in length, but this is not really surprising.)
(3) Under the Z-machine, text may only contain characters from the so-called "ZSCII" character set – standard numbers, letters, punctuation marks and the commonest West European accented letters. Anything more exotic is likely to be flattened into a question mark "?". Under Glulx, any character can be used.
All of this makes the Z-machine sound very inferior, for text purposes. But note that Z can handle all of the examples in this chapter perfectly happily.
Inform can get at the contents of text in a variety of ways. The lowest-level is by character – a character is a letter, digit, punctuation symbol, space or other letter-form. (We use the term "character" rather than "letter" because otherwise we would have to call "5" a letter, and so on.) Characters number upwards from 1: character number 1, to repeat that, starts the text. We can get the Nth character with:
This phrase produces the Nth character from the text, counting from 1. Characters include letters, digits, punctuation symbols, spaces or other letter-forms. Example:
produces "e". If the index is less than 1 or more than the length of the text, the result is an empty text, "".
The maximum character number varies with the current length of the text, and can be evaluated as:
This phrase produces the number of characters from the text. Characters include letters, digits, punctuation symbols, spaces or other letter-forms. Examples:
produce 13 and 0 respectively.
We can also use the adjective "empty":
The empty text, "", is the only one with 0 characters.
We can also extract the contents by word, again numbered from 1. Thus:
This phrase produces the Nth word from the text, counting from 1. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing that punctuation or spacing. Example:
produces "don't". If the index is less than 1 or more than the number of words in the text, the result is an empty text, "".
This phrase produces the number of words from the text. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing that punctuation or spacing. Example:
produces 5.
Note that the contraction apostrophe in "don't" doesn't count as punctuation. Because this is not always quite what we want, Inform offers two variations:
This phrase produces the Nth word from the text, counting from 1. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing the spacing, but leaving the punctuation as independent words. Example:
produces "-". The punctuated words here are "ice", "-", "hot", ",", "don't", "you", "think", "?". If two or more punctuation marks are adjacent, they are counted as different words, except for runs of dashes or periods: thus ",," has two punctuated words, but "--" and "…" have only one each. If the index is less than 1 or more than the number of punctuated words in the text, the result is an empty text, "".
This phrase produces the number of words from the text. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing the spacing, but leaving the punctuation as independent words. Example:
produces 8; see if you can find them all.
This phrase produces the Nth word from the text, counting from 1. Words for this purpose are what's left after breaking the text up at spacing (spaces, line breaks, paragraph breaks) but including all punctuation as if it were part of the spelling of the words it joins to. Example:
produces "ice-hot,". The unpunctuated words in "ice-hot, don't you think?" are "ice-hot,", "don't", "you", "think?". If the index is less than 1 or more than the number of punctuated words in the text, the result is an empty text, "".
This phrase produces the number of words from the text. Words for this purpose are what's left after breaking the text up at spacing (spaces, line breaks, paragraph breaks) but including all punctuation as if it were part of the spelling of the words it joins to. Example:
produces just 4.
Finally, on the larger scale still, we also have:
This phrase produces the Nth line from the text, counting from 1. Unless explicit use is made of line-breaking, lines and paragraphs will be the same – it doesn't refer to lines as visible on screen, because we have no way of knowing what size screen the player might have.
This phrase produces the number of lines in the text. Unless explicit use is made of line-breaking, lines and paragraphs will be the same – it doesn't refer to lines as visible on screen, because we have no way of knowing what size screen the player might have. Example: the number of lines in
is 3.
This phrase produces the Nth paragraph from the text, counting from 1.
This phrase produces the number of paragraphs in the text. Example: the number of paragraphs in
is 2.
(Attempting to make large enough texts to have a serious paragraph count is slightly risky if there is not much memory to play with, as on the Z-machine. But the facilities do exist.)
In most European languages the same letters can appear in two forms: as capitals, like "X", mainly used to mark a name or the start of a sentence; or in their ordinary less prominent form, like "x". These forms are called upper and lower case because, historically, typesetters kept lead castings of letters in two wooden cases, one above the other on the workbench. Lower case letters were in the lower box closer to hand, being more often needed.
Human languages are complicated. Not every lower case letter has an upper case partner: ordinal markers in Hispanic languages don't, for instance, and the German "ß" is never used in upper case. Sometimes two different lower case letters have the same upper case form: "ς" and "σ", two versions of the Greek sigma, both capitalise to "Σ". Inform follows the international Unicode standard in coping with all this.
We can test whether text is in either case like so:
This condition is true if every character in the text is a lower case letter. Examples: this is true for "wax", but false for "wax seal" or "eZ mOnEy".
This condition is true if every character in the text is in upper case. Examples: this is true for "BEESWAX", but false for "ROOM 101".
We can change the casing of text using:
This phrase produces a new version of the given text, but with all upper case letters reduced to lower case. Example: "a ticket to Tromsø via Østfold" becomes
This phrase produces a new version of the given text, but with all upper case letters reduced to lower case. Example: "a ticket to Tromsø via Østfold" becomes
This phrase produces a new version of the given text, but with casing of words changed to title casing: this capitalises the first letter of each word, and lowers the rest. Example: "a ticket to Tromsø via Østfold" becomes
This phrase produces a new version of the given text, but with casing of words changed to sentence casing: this capitalises the first letter of each sentence and reduces the rest to lower case. Example: "a ticket to Tromsø via Østfold" becomes
Accents are preserved in case changes. So (if we are using Glulx and have Unicode available) title case can turn Aristophanes' discomfortingly lower-case lines
by raising them proudly up like so:
Title and sentence casing can only be approximate if done by computer. Inform looks at the letters, but is blind to the words and sentences they make up. (Note the way sentence casing did not realise "Tromsø" and "Østfold" were proper nouns.) If asked to put the name "MCKAY" into title casing, Inform will opt for "Mckay", not recognising this as the Scottish patronymic surname "McKay". Given "baym dnieper", the title of David Bergelson's great Yiddish novel of 1932, it will opt for "BAYM DNIEPER": but properly speaking Yiddish does not have upper case lettering at all, though nowadays it is sometimes printed as if it did. And conventions are very variable about which words should be capitalised in titles: English publishers mostly agree that connectives, articles and prepositions should be in lower case, but in France almost anything goes, with Académie Française rules giving way to avant-garde book design. In short, we cannot rely on Inform's title casing to produce a result which a human reader will always think perfect.
This discussion has all been about how Inform prints, not about how it reads commands from the keyboard, because the latter is done case-insensitively. The virtual machines for which Inform creates programs normally flatten all command input to lower case, and in any case Understand comparison ignores casing. Thus
means that "examine McKay", "examine MCKAY", "examine mckay", and so forth are all equivalent. The text of the player's command probably doesn't preserve the original casing typed in any event.
One more caution, though it will affect hardly anyone. For projects using the Z-machine, only a restricted character set is available in texts: for more, we must use Glulx. A mad anomaly of ZSCII, the Z-machine character set, is that it contains the lower case letter "ÿ" but not its upper case form "Ÿ", so that
produces "Ÿ" in Glulx but "ÿ" in the Z-machine. This will come as a blow to Queensrÿche fans, but in all other respects any result on the Z-machine should agree with its counterpart on Glulx.
Up to now, we have only been able to judge two texts by seeing if they are equal, but we can now ask more subtle questions.
This condition is true if the second text occurs anywhere inside the first. Examples:
tests whether the digit 3 occurs anywhere in the score, as printed out; and
tests to see whether "the" can be found anywhere in the current room's name. Note that the location "Smotheringly Hot Jungle" would pass this test – it's there if you look. On the other hand, "The Orangery" would not, because "The" does not match against "the". We can get around this in a variety of ways, one of which is to tell Inform to be insensitive to the case (upper or lower) of letters:
This condition is true if the second text matches the first, starting at the beginning and finishing at the end. This appears to be the same as testing if one is equal to the other, but that's not quite true: for example,
is true if the score and best score currently print out as the same text, which will be true if they are currently equal as numbers; but
is never true – these are different texts, even if they sometimes look the same.
In the next section we shall see that "matches" and "exactly matches" can do much more than the simple text matching demonstrated above.
We can also see how many times something matches:
This produces the number of times the second text occurs within the first. The matches are not allowed to overlap. Example:
There's no "number of times WHATEVER exactly matches the text FIND" phrase since this is by definition going to have to be 0 or 1.
When playing around with text, we tend to get into longer and trickier wrangles of matching – we find that we want to look not for simple text like "gold", but for "gold" used only as a separate word, or for a date in YYYY-MM-DD format, or for a seemingly endless range of other possibilities. What we need is not just for Inform to provide a highly flexible matching program, but also a good notation in which to describe what we want.
Fortunately, such a notation already exists. This is the "regular expression" notation, named for a 1950s mathematical model by the logician Stephen Kleene, applied to computing in the late 60s by Ken Thompson, borrowed almost at once by the early Unix tools of the 70s, and developed further by Henry Spencer in the 80s and Philip Hazel in the 90s. The glue holding the Internet together – the Apache web-server, the scripting languages Perl and Python, and so forth – makes indispensable use of regular expressions.
As might be expected from the previous section, we simply have to describe the FIND text as "regular expression" rather than "text" and then the same facilities are available:
This condition is true if any contiguous part of the text can be matched against the given regular expression. Examples:
is true, since this looks for a part of "taramasalata" which begins with "a", continues with any number of characters, and finishes with "l"; so it matches "aramasal". (Not "asal", because it gets the makes the leftmost match it can.) The option "case insensitively" causes lower and upper case letters to be treated as equivalent.
This condition is true if the whole text (starting from the beginning and finishing at the end) can be matched against the given regular expression. The option "case insensitively" causes lower and upper case letters to be treated as equivalent.
And once again:
This produces the number of times that contiguous pieces of the text can be matched against the regular expression, without allowing them to overlap.
Since a regular expression can match quite a variety of possibilities (for instance "b\w+t" could match "boast", "boat", "bonnet" and so on), it's sometimes useful to find what the match actually was:
This phrase is only meaningful immediately after a successful match of a regular expression against text, and it produces the text which matched. Example:
says "masal."
Perhaps fairly, perhaps not, regular expressions have a reputation for being inscrutable. The basic idea is that although alphanumeric characters (letters, numbers and spaces) mean just what they look like, punctuation characters are commands with sometimes dramatic effects. Thus:
behave very differently. The first is just like matching the text "fish", but the second matches on any sequence of characters starting with an "f" and ending with an "h". This is not at all obvious at first sight: reading regular expressions is a skill which must be learned, like reading a musical score. A really complex regular expression can look like a soup of punctuation and even an expert will blink for a few minutes before telling you what it does – but a beginner can pick up the basics very quickly. Newcomers might like to try out and become comfortable with the features a few at a time, reading down the following list.
1. Golden rule. Don't try to remember all the characters with weird effects. Instead, if you actually mean any symbol other than a letter, digit or space to be taken literally, place a backslash "\" in front of it. For instance, matching the regular expression
is the same as matching the text "*A* of the Galactic Patrol", because the asterisks are robbed of their normal powers. This includes backslash itself: "\\" means a literal backslash. (Don't backslash letters or digits – that turns out to have a meaning all its own, but anyway, there is never any need.)
2. Alternatives. The vertical stroke "|" – not a letter I or L, nor the digit 1 – divides alternatives. Thus
is the same as saying match "the fish", or "fowl", or "crawling thing".
3. Dividing with brackets. Round brackets "(" and ")" group parts of the expression together.
is the same as saying match "the fish in question", or "the fowl in question", or "the crawling thing in question". Note that the "|" ranges outwards only as far as the group it is in.
4. Any character. The period "." means any single character. So
matches on any sequence of five characters so long as the first is "a" and the last is "z".
5. Character alternatives. The angle brackets "<" and ">" are a more concise way of specifying alternatives for a single character. Thus
matches on "bab", "beb", "bib", "bob" or "bub", but not "baob" or "beeb" – any single character within the angle brackets is accepted. Beginning the range with "^" means "any single character so long as it is not one of these": thus
matches on "blb" but not "bab", "beb", etc., nor on "blob" or "bb". Because long runs like this can be a little tiresome, we are also allowed to use "-" to indicate whole ranges. Thus
matches a "b", then any lower case English letter, then another "b".
In traditional regular expression language, square brackets rather than angle brackets are used for character ranges. In fact Inform does understand this notation if there are actual square brackets "[" and "]" in the pattern text, but in practice this would be tiresome to achieve, since Inform uses those to achieve text substitutions. So Inform allows "b<a-z>b" rather than making us type something like
to create the text "b[a-z]b".
6. Popular character ranges. The range "<0-9>", matching any decimal digit, is needed so often that it has an abbreviation: "\d". Thus
matches, say, "2006-12-03". Similarly, "\s" means "any spacing character" – a space, tab or line break. "\p" is a punctuation character, in the same sense used for word division in the previous section: it actually matches any of
"\w" means "any character appearing in a word", and Inform defines it as anything not matching "\s" or "\p".
"\l" and "\u" match lower and upper case letters, respectively. These are much stronger than "<a-z>" and "<A-Z>", since they use the complete definition in the Unicode 4.0.0 standard, so that letter-forms from all languages are catered for: for example "δ" matches "\l" and "Δ" matches "\u".
The reverse of these is achieved by capitalising the letter. So "\D" means "anything not a digit", "\P" means "anything not punctuation", "\W" means "anything not a word character", "\L" means "anything not a lower case letter" and so on.
7. Positional restrictions. The notation "^" does not match anything, as such, but instead requires that we be positioned at the start of the text. Thus
matches only "fish" at the start of the text, not occurring anywhere later on. Similarly, "$" requires that the position be the end of the text. So
matches only if the last four characters are "fish". Matching "^fish$" is the same thing as what Inform calls exactly matching "fish".
Another useful notation is "\b", which matches a word boundary: that is, it matches no actual text, but requires the position to be a junction between a word character and a non-word character (a "\w" and a "\W") or vice versa. Thus
matches "fish" in "some fish" and also "some fish, please!", but not in "shellfish". (The regular expression "\w*fish\b" catches all words ending in "fish", as we will see below.) As usual, the capitalised version "\B" negates this, and means "not at a word boundary".
8. Line break and tab. The notations "\n" and "\t" are used for a line break ("n" for "new line") and tab, respectively. Tabs normally do not occur in Inform strings, but can do when reading from files. It makes no sense to reverse these, so "\N" and "\T" produce errors.
9. Repetition. Placing a number in braces "{" and "}" after something says that it should be repeated that many times. Thus
matches only on "axxxxxxxxxxxxxxxxxxxxxxxxx". More usefully, perhaps, we can specify a range of the number of repetitions:
matches only on "axx", "axxx", "axxxx", "axxxxx", "axxxxxx". And we can leave the top end open: "ax{2,}" means "a" followed by at least two "x"s.
Note that the braces attach only to most recent thing – so "ax{2}" means "a" followed by two of "x" – but, as always, we can use grouping brackets to change that. So "(ax){2,}" matches "axax", "axaxax", "axaxaxax",…
(It's probably best not to use Inform to try to match the human genome against "<acgt>{3000000000}", but one of the most important practical uses of regular expression matching in science is in treating DNA as a string of nucleotides represented by the letters "a", "c", "g", "t", and looking for patterns.)
10. Popular repetitions. Three cases are so often needed that they have standard short forms:
"{0,1}", which means 0 or 1 repetition of something – in other words, doesn't so much repeat it as make it optional – is written "?". Thus "ax?y" matches only on "ay" or "axy".
"{0,}", which means 0 or more repetitions – in other words, any number at all – is written "*". Thus "ax*y" matches on "ay", "axy", "axxy", "axxxy", … and the omnivorous ".*" – which means "anything, any number of times" – matches absolutely every text. (Perhaps unexpectedly, replacing ".*" in a text with "X" will produce "XX", not "X", because the ".*" first matches the text, then matches the empty gap at the end. To match the entire text just once, try "^.*$".)
"{1,}", which means 1 or more repetitions, is written "+". So "\d+" matches any run of digits, for instance.
11. Greedy vs lazy. Once we allow things to repeat an unknown number of times, we run into an ambiguity. Sure, "\d+" matches the text "16339b". But does it look only as far as the "1", then reason that it now has one or more digits in a row, and stop? Or does it run onward devouring digits until it can do so no longer, so matching the "16339" part? These two strategies are called "lazy" and "greedy" respectively.
Do we care? Well, the strategy used makes no difference to whether there is a match, but it does affect what part of the text is matched, and the number of matches there are. Unless we mark for it, all repetitions are greedy. Usually this is good, but it means that, for instance,
applied to "-alpha- -beta- -gamma-" will match the whole text, because ".+" picks up all of "alpha- -beta- -gamma". To get around this, we can mark any of the repetition operators as lazy by adding a question mark "?". Thus:
applied to "-alpha- -beta- -gamma-" matches three times, producing "-alpha-" then "-beta-" then "-gamma-".
A logical but sometimes confusing consequence is that a doubled question mark "??" means "repeat 0 or 1 times, but prefer 0 matches to 1 if both are possibilities": whereas a single question mark "?", being greedy, means "repeat 0 or 1 times, but prefer 1 match to 0 if both are possibilities".
12. Numbered groups. We have already seen that round brackets are useful to clump together parts of the regular expression – to choose within them, or repeat them. In fact, Inform numbers these from 1 upwards as they are used from left to right, and we can subsequently refer back to their contents with the notation "\1", "\2", … After a successful match, we can find the results of these subexpressions with:
This phrase is only meaningful immediately after a successful match of a regular expression against text, and it produces the text which matched. The number must be from 1 to 9, and must correspond to one of the bracketed groups in the expression just matched. Example: after
the "text matching regular expression" is "aramasalat", the "text matching subexpression 1" is "ramasal", and "text matching subexpression 2" is "t".
For instance:
matches any run of two or more word-characters, subject to the restriction that the last one has to be the same as the first – so it matches "xerox" but not "alphabet". When Inform matches this against "xerox", first it matches the initial "x" against the group "(\w)". It then matches "\w*" ("any number of word-characters") against "ero", so that the "*" runs up to 3 repetitions. It then matches "\1" against the final "x", because "\1" requires it to match against whatever last matched in sub-expression 1 – which was an "x".
Numbered groups allow wicked tricks in matching, it's true, but really come into their own when it comes to replacing – as we shall see.
13. Switching case sensitivity on and off. The special notations "(?i)" and "(?-i)" switch sensitivity to upper vs. lower case off and on, mid-expression. Thus "a(?i)bcd(?-i)e" matches "abcde", "aBcDe", etc., but not "Abcde" or "abcdE".
14. Groups with special meanings. This is the last of the special syntaxes: but it's a doozy. A round-bracketed group can be marked to behave in a special way by following the open bracket by a symbol with a special meaning. Groups like this have no number and are not counted as part of \1, \2, and so forth – they are intended not to gather up material but to have some effect of their own.
Is a comment, that is, causes the group to do nothing and match against anything.
Is a lookahead: it is a form of positional requirement, like "\b" or "^", but one which requires that the text ahead of us matches whatever is in the brackets. (It doesn't consume that text – only checks to see that it's there.) For instance "\w+(?=;)" matches a word followed by a semicolon, but does not match the semicolon itself.
Is the same but negated: it requires that the text ahead of us does not match the material given. For instance, "a+(?!z)" matches any run of "a"s not followed by a "z".
Are the same but looking behind (hence the "<"), not forward. These are restricted to cases where Inform can determine that the material to be matched has a definite known width. For instance, "(?<!shell)fish" matches any "fish" not occurring in "shellfish".
Is a possessive, that is, causes the material to be matched and, once matched, never lets go. No matter what subsequently turns out to be convenient, it will never change its match. For instance, "\d+8" matches against "768" because Inform realises that "\d+" cannot be allowed to eat the "8" if there is to be a match, and stops it. But "(>\d+)8" does not match against "768" because now the "\d+", which initially eats "768", is possessive and refuses to give up the "8" once taken.
Are conditionals. These require us to match the material given if \1 has successfully matched already; in the second version, the material after the "|" must be matched if \1 has not successfully matched yet. And the same for 2, 3, …, 9, of course.
Finally, conditionals can also use lookaheads or lookbehinds as their conditions. So for instance:
means if you start with a digit, match four digits; otherwise match "AY-" followed by four digits. There are easier ways to do this, of course, but the really juicy uses of conditionals are only borderline legible and make poor examples – perhaps this is telling us something.
Substitutions are most often used just for printing, like so:
But they can also produce text which can be stored up or used in other ways. For example, defining
makes
set this temporary variable to "NewYorkNewYork".
There is, however, a subtlety here. A text with a substitution in it, like:
is always waiting to be substituted, that is, to become something like:
If all we do with text is to print it, there's nothing to worry about. But if we're storing it up, especially for multiple turns, there are ambiguities. For example, suppose we're changing the look of the black status line bar at the top of the text window:
Just copying "[time of day]" to the "left hand status line" variable doesn't make it substitute – which is just as well, or the top of the screen would perpetually show "9:00 AM".
On the other hand, looking back at the phrase example:
"[T][T]" is substituted immediately it's formed. That's also a good thing, because "T" loses its meaning the moment the phrase finishes, which would make "[T][T]" meaningless anywhere else.
What's going on here is this: Inform substitutes text immediately if it contains references to a temporary value such as "T", and otherwise only if it needs to access the contents. This is why "[time of day]" isn't substituted until we need to print it out (or, say, access the third character): "time of day" is a value which always exists, not a temporary one.
Another case where that might be important is if we want to set a text to an elaborated version of itself. For example, suppose there is a variable (not a temporary one) called "the accumulated tally", and consider this:
The intention of the writer here was to add an "X" each time this happens. But the result is a hang, because what it actually means is that accumulated tally can only be printed if the accumulated tally is printed first… an infinite regress. The safe way to do this would be:
Using the adjectives "substituted" and "unsubstituted", it's always possible to test whether a given text is in either state, should this ever be useful. For example,
will say "Yes!": the LHSL is like a bomb waiting to go off. Speaking of which:
This is making use of:
This takes a text and makes substitution occur immediately. For example,
produces something like "time of death, 9:15 AM" rather than "time of death, [time of day]". It's entirely legal to apply this to text which never had any substitutions in, so
produces "balloon".
Note that there's no analogous phrase for "unsubstituted form of…", because once text has substituted, there's no way to go back.
Suppose V is a text which varies – perhaps a property of something, or a variable defined everywhere, or a temporary "let"-named value. How do we change its contents? The easiest way is simply to assign text to it. Thus:
And, for instance,
adds an exclamation mark at the end of V.
Otherwise, it is more useful (also a little faster) to modify V by changing its characters, words and so on. Thus:
This phrase acts on the named text by placing the given text in place of the Nth character, counting from 1. Example:
says "molecule".
This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing or punctuation. Example:
says "Does the jogger run dry?".
This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing, counting punctuation runs as words in their own right. Example:
says "Frankly: yes, I agree.".
This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing, counting punctuation as part of a word just as if it were lettering. Example:
says "Frankly, of course I agree.".
This phrase acts on the named text by placing the given text in place of the Nth line, counting from 1. Lines are divided by paragraph or line breaks.
This phrase acts on the named text by placing the given text in place of the Nth paragraph, counting from 1.
Last, but not least, we can replace text wherever it occurs:
This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible. Example:
changes every lower-case "a" to "z": the same thing done with the "case insensitively" option would change each "a" or "A" to "z".
All very well for letters, but it can be unfortunate to try
if V happens to contain, say "The Olympic Bobsleigh Team": it would become "The Olympic Robertsleigh Team". What we want, of course, is for Bob to become Robert only when it's a whole word. We can get that with:
This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible, where the search text must occur as a whole word. Example:
changes "Bob got on the Bobsleigh" to "Robert got on the Bobsleigh".
This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible, where the search text must occur as a whole word or run of punctuation.
But these are all just special cases of the grand-daddy of all replacement phrases:
This phrase acts on the named text by matching the regular expression and replacing anything which fits it, as many non-overlapping times as possible. Example:
changes "The Battle of Waterloo, 1815, rivalled Trafalgar, 1805" to "The Battle of Waterloo, …, rivalled Trafalgar, …". The "case insensitively" causes lower and upper case letters to be treated as if the same letter.
When replacing a regular expression, the replacement text also has a few special meanings (though, thankfully, many fewer than for the expression itself). Once again "\n" and "\t" can be used for line break and tab characters, and "\\" must be used for an actual backslash. But, very usefully, "\1" to "\9" expand as the contents of groups numbered 1 to 9, and "\0" to the exact text matched. So:
adds the word "roughly" in front of any run of digits in V, because \0 becomes in turn whichever run of digits matched. And
performs the transformation "Frank Booth" to "Booth, Frank".
Finally, prefixing the number by "l" or "u" forces the text it represents into lower or upper case, respectively. For instance:
changes the casing of X to "title casing", where each individual word is capitalised. (This is a little slow on large texts, since so many matches and replacements are made: it's more efficient to use the official phrases for changing case.)
MATCHING
Positional restrictions
| ^ | Matches (accepting no text) only at the start of the text |
| $ | Matches (accepting no text) only at the end of the text |
| \b | Word boundary: matches at either end of text or between a \w and a \W |
| \B | Matches anywhere where \b does not match |
Backslashed character classes
| \char | If char is other than a-z, A-Z, 0-9 or space, matches that literal char |
| \\ | For example, this matches literal backslash "\" |
| \n | Matches literal line break character |
| \t | Matches literal tab character (but use this only with external files) |
| \d | Matches any single digit |
| \l | Matches any lower case letter (by Unicode 4.0.0 definition) |
| \p | Matches any single punctuation mark: . , ! ? - / " : ; ( ) [ ] { } |
| \s | Matches any single spacing character (space, line break, tab) |
| \u | Matches any upper case letter (by Unicode 4.0.0 definition) |
| \w | Matches any single word character (neither \p nor \s) |
| \D | Matches any single non-digit |
| \L | Matches any non-lower-case-letter |
| \P | Matches any single non-punctuation-mark |
| \S | Matches any single non-spacing-character |
| \U | Matches any non-upper-case-letter |
| \W | Matches any single non-word-character (i.e., matches either \p or \s) |
Other character classes
| . | Matches any single character |
| <...> | Character range: matches any single character inside |
| <^...> | Negated character range: matches any single character not inside |
Inside a character range
| e-h | Any character in the run "e" to "h" inclusive (and so on for other runs) |
| >... | Starting with ">" means that a literal close angle bracket is included |
| \ | Backslash has the same meaning as for backslashed character classes: see above |
Structural
| | | Divides alternatives: "fish|fowl" matches either |
| (?i) | Always matches: switches to case-insensitive matching from here on |
| (?-i) | Always matches: switches to case-sensitive matching from here on |
Repetitions
| ...? | Matches "..." either 0 or 1 times, i.e., makes "..." optional |
| ...* | Matches "..." 0 or more times: e.g. "\s*" matches an optional run of space |
| ...+ | Matches "..." 1 or more times: e.g. "x+" matches any run of "x"s |
| ...{6} | Matches "..." exactly 6 times (similarly for other numbers, of course) |
| ...{2,5} | Matches "..." between 2 and 5 times |
| ...{3,} | Matches "..." 3 or more times |
| ....? | "?" after any repetition makes it "lazy", matching as few repeats as it can |
Numbered subexpressions
| (...) | Groups part of the expression together: matches if the interior matches |
| \1 | Matches the contents of the 1st subexpression reading left to right |
| \2 | Matches the contents of the 2nd, and so on up to "\9" (but no further) |
Unnumbered subexpressions
| (# ...) | Comment: always matches, and the contents are ignored |
| (?= ...) | Lookahead: matches if the text ahead matches "...", but doesn't consume it |
| (?! ...) | Negated lookahead: matches if lookahead fails |
| (?<= ...) | Lookbehind: matches if the text behind matches "...", but doesn't consume it |
| (?<! ...) | Negated lookbehind: matches if lookbehind fails |
| (> ...) | Possessive: tries to match "..." and if it succeeds, never backtracks on this |
| (?(1)...) | Conditional: if \1 has matched by now, require that "..." be matched |
| (?(1)...|...) | Conditional: ditto, but if \1 has not matched, require the second part |
| (?(?=...)...|...) | Conditional with lookahead as its condition for which to match |
| (?(?<=...)...|...) | Conditional with lookbehind as its condition for which to match |
IN REPLACEMENT TEXT
| \char | If char is other than a-z, A-Z, 0-9 or space, expands to that literal char |
| \\ | In particular, "\\" expands to a literal backslash "\" |
| \n | Expands to a line break character |
| \t | Expands to a tab character (but use this only with external files) |
| \0 | Expands to the full text matched |
| \1 | Expands to whatever the 1st bracketed subexpression matched |
| \2 | Expands to whatever the 2nd matched, and so on up to "\9" (but no further) |
| \l0 | Expands to \0 converted to lower case (and so on for "\l1" to "\l9") |
| \u0 | Expands to \0 converted to upper case (and so on for "\u1" to "\u9") |
Many sections in this book begin by introducing a new kind of value. Reading through in order, the possibilities mount up: numbers, times, texts, and so on. (See the Kinds page of the Index for a convenient list of the options.) This section is a little different: rather than showing a single new kind of value, it shows how to make a new kind out of any existing one.
If K is any kind of value, then "list of K" is also a kind of value. For instance, we could write:
and this would create a new "let" variable, called L, whose kind of value is "list of numbers". On the other hand, we are not allowed to write:
because "list" by itself is not a kind of value. (Inform always needs to know what kinds the values entered in a list are going to have.)
Lists are like flexible-length table columns, but that probably makes them sound more mysterious than they really are. A list is simply a sequence of values, called its "entries", numbered from 1 upwards. The number of entries is called its "length". If we try
then we find
This is because all lists start out empty when created: that is, they initially have 0 entries. Inform has two built-in adjectives "empty" and "non-empty" which can apply to lists, and they mean just what they ought to mean: a list is empty if its length is 0, and otherwise non-empty.
We can add entries very easily:
We can now, for instance, try saying the list:
with the result
Note that only numbers can be added to L: if we try
Inform will produce a problem message, because L has kind "list of numbers", whereas "clock" is text. In this way, Inform ensures that a list always contains values of the same kind throughout. So it's not possible to construct a list whose entries are:
Such a list would be very hazardous to deal with, in any case. If what we need is a combination of different kinds of values, tables are a better option.
Finally, note that since "list of numbers" is a kind of value in its own right, so is "list of lists of numbers", and so on – though such lists are trickier to deal with, they are sometimes handy.
It is convenient to have a concise way to write down a constant list. Just as we could write "231", say, or "7:01 AM" to refer to particular number and time constants, so we can write list constants:
Inform recognises that "{1, 2, 3, 4}" is a list because of the braces, and looks at the entries inside, sees that they are numbers, and deduces that it is a constant whose kind of value is "list of numbers". L is then a temporary list variable and we can add to it, remove things, and so on as we please – {1, 2, 3, 4} is merely its initial value.
When constructing lists, it is worth noting that Inform requires spaces after the commas (which seems a little harsh, but is necessary because otherwise many sensible literal specifications for units would be impossible – anyway, the reason isn't important here). So
would produce problem messages. But Inform does not require spaces round its braces.
We call this way of writing a list "brace notation". In mathematics, braces are usually used for sets, and properly speaking these are sequences not sets – so that "{1, 2, 3, 4}" is different from "{4, 3, 2, 1}" – but it is still a familiar notation. Similarly,
makes L a list of texts; and
makes a global variable ("list of prohibited items") with kind of value "list of objects", and whose initial value is to contain two things: the firework and the stink bomb. More exotically, if we need to make lists of lists:
gives L the kind of value "list of lists of numbers", with (initially) two entries: the list {1, 2} (a list of numbers), then the list {6, 7, 8} (ditto).
Constant lists are convenient, too, when a column in a table needs to contain lists:
| recipe | ingredients |
| "duck à l'orange" | {the duck, the orange} |
| "spiced cider" | {the cider, the cinnamon, the orange} |
A special word about the constant list "{ }". This means the list with no entries – the empty list. If we try to create a new "let" variable M with
then Inform will produce a problem message, because it cannot tell what sort of list M will be: a list of numbers, or texts, or times, or…? On the other hand, writing
is fine if M already exists, and then does the obvious thing – empties M. Similarly, a table column in which every entry is "{ }" produces a problem message unless the heading for that column spells out the kind of value stored within it: for instance, "ingredients (list of texts)".
All of this is a notation for constant lists only, not some sort of gluing-things-together operation. So this, for instance:
is not allowed, even though "the turn count" is a number: because it is a number that varies, the braces do not contain constants, and therefore this is not a list constant.
Any list L can be said, provided that its contents can be said. For example:
produces the text "2, 3, 5, 7 and 11" – unless we have "Use serial comma." set, in which case a comma appears after the 7. We also have the option of using the more formal notation:
This text substitution produces the list in the form of "{", then a comma-separated list, and then "}", which looks less like an English sentence but more mathematical. Example:
might produce "{ yourself, Mr Darcy, Flashman }".
If we say a list of lists, then the individual entry lists are always printed in brace notation: the ordinary sentence way would be incomprehensible.
Of course, the values in L1 are written out in number form because L1 is a list of numbers: we could alternatively try
which produces "piano and music stand". Lists of objects can be said in two additional ways:
This text substitution writes out the list in sentence form, adding the appropriate definite articles. Example:
says "the piano and the music stand".
This text substitution writes out the list in sentence form, adding the appropriate indefinite articles. Example:
says "a piano and a music stand".
If L is a list, we can interrogate it to see whether it does or does not contain (at least one instance of) any compatible value V:
This condition is true if the given value, which must be of a compatible kind, is one of those in the list. For instance, if L is our list of the numbers 2, 3, 5, 7 and 11 then 5 is listed in it but 6 is not.
This condition is true if the given value, which must be of a compatible kind, is not one of those in the list.
We can also repeat running through a list (just as we can with table rows). Thus:
This phrase causes the block of phrases following it to be repeated once for each item in the given list, storing that value in the named variable. (The variable exists only temporarily, within the repetition.) Example:
If the list is empty, nothing happens: the "…" phrase(s) are never tried.
In the next sections, we shall see that it is possible to change, reorder and resize lists. But it's important never to change a list that's being repeated through. The following:
leaves L1 containing {2, 4}, since the removals from the list cause it to shuffle back even while we repeat through it – a bad, bad idea.
We have already seen "add… to…". This in fact comes in two forms:
This phrase adds the given value to the end of the list. Example:
results in L being {60, 168, 360}. Note that the value is added even if it already occurs somewhere in L; this can be avoided with "if absent". So:
would do nothing – it is already there.
This phrase adds the first list to the end of the second. Example:
results in L being {2, 3, 5, 7, 11, 13, 17, 19}.
If we don't want to add new entries at the end, we can instead say where they should go:
This phrase adds the given value so that it becomes the entry with that index number in the list. Example:
sets L to {1, 2, 3, 4, 8, 12, 24}. If there are N entries in L, then we can add at any of entries 1 up to N+1: adding at entry N+1 means adding at the end. The phrase option "if absent" makes the phrase do nothing if the value already exists anywhere in L.
This phrase adds the first list to the second so that it begins at the given position. Example:
results in L being {1, 2, 4, 8, 12, 3, 4}.
A list is allowed to contain duplicates, and the order matters. For instance:
makes L into "2, 2 and 3". This is a different list to the one made by:
even though L and M have the same values, repeated the same number of times – for two lists to be equal, they must have the same kind of entry, the same number of entries, and the same entries in each position.
We can also strike out values:
This phrase removes every instance of the given value from the list. Example:
results in L being {3, 4, 5, 9, 2, 6, 5, 3}. Ordinarily "remove 7 from L" would produce a run-time problem, since L does not contain the value 7, but using the "if present" option lets us off this: the phrase then does nothing if L does not contain the value to be removed.
This phrase removes every instance of any value in the first list from the second. Example:
results in L being {3, 1, 1, 5, 9, 5, 3}. If both lists are large, this can be a slow process, and we might do better by sorting them and trying a more sophisticated method. But this is convenient for anything reasonable-sized.
Again, we can also remove from specific positions:
This phrase removes the entry at the given position, counting from 1 as the first entry. (Once it is removed, the other entries shuffle down.) Example:
results in L being {3, 1, 1, 5, 9, 2, 6, 5, 3}.
This phrase removes the entries at the given range of positions, counting from 1 as the first entry. (Once they are removed, the other entries shuffle down.) Example:
results in L being {3, 1, 2, 6, 5, 3}.
Lists can be made of values of any kind (including other lists), but lists of objects are especially useful. We could always make these "by hand":
But it is usually easier and clearer to use descriptions.
This phrase produces the list of all values matching the given description. Inform will issue a problem message if the result would be an infinite list, or one which is impractical to test: for instance "list of even numbers" is not feasible.
While that works nicely for many kinds of value ("list of recurring scenes", say), it's particularly useful for objects:
means that L now contains the open containers (if any) followed by the open doors (if any). Or, for example:
makes a list of all non-backdrops.
As mentioned above, lists of objects can be said in two additional ways:
And as mentioned below, they can be sorted in property value order:
where P is any value property. In all other respects, lists of objects are no different to other lists.
The useful "list of …" syntax can also be used to produce lists of the values matching a description, too. Thus:
There is little to say here except for the usual warning that some kinds of value have a range which is too large to make this possible. For instance, Inform could not sensibly represent:
It would just be too large to hold. In general, if we can repeat through, or find the number of, values matching a description, then we can also use "list of" to bring them all together. See the chart of kinds of value in the Kinds index for a project for which kinds of value allow this.
Any list L can be reversed:
This phrase puts the list in reverse order. The old entry 1 becomes the new last entry, and so on: reversing an empty list or a list containing only one entry leaves it unchanged. Example:
results in L being {17, 16, 15, 14, 12, 11}.
And any list can similarly be sorted:
This phrase puts the list into ascending order. Example:
results in L being {9:01 AM, 11:13 AM, 4:21 PM, 6 PM}.
This phrase puts the list into descending order. Example:
results in L being {6 PM, 4:21 PM, 11:13 AM, 9:01 AM}.
This phrase puts the list into a uniformly random order, shuffling it as if it were a pack of cards. Example:
might result in L being {3, 1, 5, 6, 4, 2}. Or any of 719 other arrangements, including being left as it was.
Lists of objects can also be sorted in property value order. For instance,
This phrase puts the list into ascending order of the values of the given property for the items in the list; this is only allowed if all of those values do have the property in question. Example:
would arrange people with weaklings first, titans last.
This phrase puts the list into descending order of the values of the given property for the items in the list; this is only allowed if all of those values do have the property in question. Example:
would arrange people with titans first, weaklings last.
Rotating a list means moving all of its entries along by one place, and then moving the one on the end back to the start. For instance, if L is {1, 2, 3, 4}, then
This phrase shuffles the entries of the list forwards (to the right) by one place, so that the 1st becomes 2nd, the 2nd becomes 3rd, and so on until the last, which becomes the new first entry. Example:
results in L being { "bullock", "cow", "heifer" }.
This phrase shuffles the entries of the list backwards (to the left) by one place, so that the 3rd becomes 2nd, the 2nd becomes 1st, and so on; the previous 1st entry becomes the new last entry. Example:
results in L being { "heifer", "bullock", "cow"}. (This achieves the same effect as "reverse L; rotate L; reverse L;" but is a little faster, and a lot less effort to read.)
The length of a list can change as values are added or removed, and can in principle be any number from 0 upwards. A list with 0 entries is empty. We can find the length with:
This phrase produces the number of positions in the list. Example:
is 5, even though there are only two genuinely different items in the list.
If the length is N then the entries are numbered from 1 (the front) to N (the back). These entries can be accessed directly by their numbers. For instance,
refers to the second entry of L: it can be used as a value, or changed, just as if it were a named variable. For instance, we could write:
which would (untruthfully) print "The rain in Spain stays mainly in the plain", but only if L had an entry 7 to make use of: if L were a list of 5 entries, say, then a run-time problem results. (And if L cannot hold text, a problem message means that we never get as far as run-time.) Because entries number from 1, this is always incorrect:
and if L is currently empty, then there is no entry which can be accessed, so that any use of "entry … of L" would produce a run-time problem. There are programming languages in the world where accessing entry 100 in a 7-entry list automatically extends it to be 100 entries long: Inform is not one of them. But see the next section for how to change list lengths explicitly.
We can explicitly change the length of a list like so:
This phrase alters the given list so that it now has exactly the number of entries given. Example:
If L previously had more than 21 entries, they are thrown away (and lost forever); if L previously had fewer, then new entries are created, using the default value for whatever kind of value L holds. So extending a list of numbers will pad it out with 0s, but extending a list of texts will pad it out with the empty text "", and so on.
We can also write the equivalent phrases:
This phrase alters the given list so that it now has no more than the number of entries given. Example:
shortens L to length 8 if it is currently longer than that, trimming entries from the end, but would (for instance) leave a list of length 3 unchanged. Note that
empties it to { }, the list with nothing in.
This phrase alters the given list so that it now consists only of the initial part of the list with the given length. Example:
turns {1, 3, 5, 7, 9, 11} to {1, 3, 5, 7}.
This phrase alters the given list so that it now consists only of the final part of the list with the given length. Example:
turns {1, 3, 5, 7, 9, 11} to {5, 7, 9, 11}.
But we don't have to truncate: we can also -
This phrase pads out the list with default values as needed so that it now has at least the given length. (If the list is already at least that length, nothing is done.) Example:
lengthens L to length 80 if it is currently shorter than that.
For example,
builds a list of N numbers (initially all 0), fills it with the numbers 1, 2, 3, …, N, then randomly reorders them, then sorts them back again, recovering the original order. The text produced by "check sorting 10" depends partly on chance but might for instance be:
As with text in the previous chapter, a project which needs really long lists should use the Glulx virtual machine – "check sorting 10000", for instance, would break the default memory environment on the Z-machine, which is very tight, but works fine (if not very rapidly) on Glulx.
Lists are highly adaptable, and many other collection-like constructions can be made using them. This section introduces no new material, but simply suggests some of the variations which are possible.
1. The traditional computing term array means a list of values accessed by their entry numbers, often used in mathematical computations. The difference between an array and a list is mostly one of attitude, but usually arrays are fixed in length whereas lists can expand or contract.
2. A log is a list which records the most recently arrived values, but does not allow itself to grow indefinitely. In the following, which remembers the seven most recently taken items, new values arrive at the end while old ones eventually disappear from the front:
Note that the most-recently-taken list begins play as the empty list, grows as the first few items are taken, but then stabilises at length 7 thereafter. If we need to remember recent history, but only recent history, then a log is better than a list which can grow indefinitely, because there is no risk of speed reduction or memory exhaustion in a very long story.
3. A queue is a list of values which are waiting for attention. New values join at the back, while those being dealt with are removed from the front (whereupon the whole queue moves up one). An empty queue means that nobody is waiting for attention: but there is, in principle, no upper limit to the size of a queue, as anyone who has tried to make a couchette reservation at Roma Termini will know.
Queues typically form when two independent processes are at work, but going at different or variable speeds. An empty queue looks just like any other list:
(Invariably people, in what follows, but we'll make it a "list of objects" to allow for other possibilities too.) Once we identify a "new customer", we can join him to the queue thus:
The process of serving the customers needs to make sure there is actually somebody waiting in the queue before it does anything:
Of course queues can also be constructed which empty from other positions, rather than the front: or we could make what computer scientists sometimes call a deque, a "double-ended queue" where new values arrive at both ends.
4. A stack is like a queue except that values arrive at, and are removed from, the same end. Stacks are slightly faster if the active end is the back rather than the front, though this will only be noticeable if they grow quite large.
To put a value V onto a stack S (which is known as "pushing") is simple:
And to remove a value from the top of the stack (which is known as "pulling"):
Note that the middle line, accessing entry N, will fail if N = 0, that is, if the stack is empty: Inform's list routines will produce a run-time problem message.
Stacks are useful if some long-term process is constantly being interrupted by newer and more urgent demands, but they can also be used in planning. If a character has a long-term goal, which needs various short-term goals to be achieved along the way, then a stack can represent the goals currently being pursued. The top of the stack represents what the character is trying to achieve now. If the character realises that it needs to achieve something else first, we put that new goal onto the top of the stack, and it becomes the new current goal. When the character completes a task, it can be removed, and we can go back to trying to finish whatever is now on top. When the stack is empty, the character has achieved the original goal.
5. Notoriously, set has 464 distinct meanings in the Oxford English Dictionary, making it the single most ambiguous word in the language. Here we mean not the home of a badger or the Egyptian god of the desert, but the mathematical sense: a collection of values (sometimes called "elements") without duplicates, and which is normally written in brace notation and in some natural order for the reader's convenience.
The trick here is to maintain the principle that, at all times, our list is sorted in order and contains no duplicates. To provide an example, we start with two sets of numbers:
Here we add an element to T:
The "if absent" clause ensures that no duplicate can occur, and by sorting T afterwards, we maintain the principle that a set must remain in order – so T is now {2, 4, 6, 8, 10}, not {2, 4, 6, 10, 8}. (Inform's sorting algorithm is fast on nearly-sorted lists, so frequent sorting is not as inefficient as it might look.)
We next take the union of T and S, that is, the set containing everything which is in either or both:
This makes U = {2, 4, 6, 8, 10, 16, 32, 64}, and once again no duplicates occur and we preserve the sorting. The intersection of T and S, the set of elements in both of them, is a little trickier:
(Faster methods could be devised which exploit the sortedness of T and S, but are not worth it for shortish lists.) This produces I = {2, 4, 8}. Lastly, we can form the set difference, consisting of those elements which are in S but not in T:
Here, as with intersection, since all we do is to strike out unwanted elements, the surviving ones remain in order and there is no need to sort when we are finished. This produces D = {16, 32, 64}.
6. A sieve is used to make a complicated choice where there are many constraints, by ruling out impossible cases to see what is left. The term derives from the kitchen utensil (for sieving fine grains of flour), but via the name of the "sieve of Eratosthenes", an ancient Greek method for determining the prime numbers.
Using a sieve is much like using a set, and the difference is mainly one of outlook – we are interested in what does not belong, rather than what does.
7. A ring is not so much a row of values, more a circle, with the last and first entries thought of as adjacent. One position is usually thought of as special, and is the place where new items are added: this may as well be entry 1. For instance, to add "new item" to the ring:
To set "item" to the frontmost value and extract it from the ring:
And we can rotate the ring in either direction, making a different entry the new entry 1 and therefore the new frontmost value:
A last note to conclude the chapter on lists. Lists, like almost all other values in Inform, can be passed to phrases as parameters. However, note that they are genuine values, not what some programming languages call "references" or "pointers". So the following:
does nothing, in practice. If given a list, it adds 7 to the list, but then throws it away again, so the longer list is never seen; it's exactly like
which can never affect anything other than its own temporary value "N", which expires almost immediately in any case.
If we want a phrase which changes a list in a useful way and gives it back to us, we need a phrase which both takes in and gives back:
And then, for example -
produces:
Most of the time, what's created in an Inform source text will have a name which can be used as a value – sometimes openly so, sometimes not. In this book, we haven't gone out of our way to make that point, because there was no real need to do so. It's possible to make heavy use of rulebooks and write large-scale Inform projects without ever needing to use a rulebook's name as a value in its own right, for example. But if we want to create sophisticated extensions to Inform, or to use modern techniques such as functional and generic programming, we need to be fluent in the language of kinds.
Inform's language of kinds has four ingredients: base kinds, constructions, kind variables and kinds of kinds.
1. Base kinds. Inform provides the following base kinds for values:
together with a few others, such as "response" and "verb", to do with linguistic features.
And Inform allows us to create new base kinds either by making more specialised kinds of object:
Or by making new enumerations or arithmetical kinds:
2. Constructions. These are ways to make new kinds from existing ones. The construction most often used is "list of…". For any kind K, there is a kind called list of K. So the range of possible kinds in Inform is actually infinite, because:
are all different from each other. Inform has nine constructions, as follows:
Some of these have appeared in previous chapters, but in abbreviated form. For example, "rulebook" abbreviates "action based rulebook producing nothing", and "either/or property" is a synonym for "truth state valued property". The kinds of descriptions and phrases haven't been covered yet, but are coming up in the sections following.
These constructions can of course be combined:
Brackets can be used to clarify matters:
Nothing will make that a simple idea, but it's unambiguous and can be puzzled out with practice.
3. Variables. In a way, that's everything: there are just base kinds and constructions on them, and those construct every possible kind in Inform. But the language we use to describe kinds is larger than that, because it allows us to describe many kinds at once, in the same way that Inform reads the word "something" as applying to many objects at once, not as a single object.
Kind variables will be covered later in the chapter, but the idea is that:
allows us to describe the kinds acceptable in a phrase so that a wide range of possibilities are allowed. The above matches both:
The letter K in the definition stood for any kind; in the first use of "hunt" here, K turned out to be "number", and in the second it was "text". On the other hand Inform would reject:
because there is no kind K which can make this match the definition.
There are potentially 26 kind variables, A to Z, though it's customary to use them in the order K, L, M, …, and it's very rare to need more than two at a time.
4. Kinds of kind. Inform understands several names which look as if they are kinds, but actually aren't:
(Again, these are built in to Inform.) They are not kinds because they're just too loose and vague. Instead, they can be used in phrase definitions to match against multiple possibilities:
This makes "announce X" work for any value X which can be said. All the same, "sayable value" is not a kind. It could never be safe for this to be the kind of a variable, because Inform would never know what could be done with the contents (except that it could be printed out).
5. Secret inner workings. There isn't a fifth ingredient, but if there were, it would be a handful of names used in matching some of the core built-in phrases of Inform which have so-called inline I6 definitions. These are not intended for anyone else to use, and are just an internal convenience; they aren't publicly documented and might change without notice. They don't describe kinds at all, because they tell the matcher to look for something else instead. For instance, there's one called "condition", which means "match a condition rather than a value". They appear in red ink in the Phrasebook index.
In the chapter on Descriptions, we saw that a description can be any source text which describes one or more objects: it might be as simple as "the Corn Market", or as complicated as "open containers which are in dark rooms". More or less the only restriction is that it must be unambiguous as to what counts and what does not: "three containers" is ambiguous as a description because it does not say which three.
We've now seen several interesting tricks with descriptions. In fact, if D is a description, then
are all standard things to do. These examples make it look as if it must be possible to define phrases which act on descriptions, and in fact it is, because a description can be a value in itself. For example,
are values of kind "description of numbers" and "description of objects" respectively. In general, if K is any kind then "description of K" is also a kind. Here is how we might make use of that:
This makes "enumerate lighted rooms" run off a list of lighted rooms in a textual format different from the standard one produced by "say the list of lighted rooms". Inside the definition, "collection" can be used wherever a description might be used: here, for instance, we use it as the range for the repeat loop. (That's only possible because the range is limited in size: Inform wouldn't have allowed us to range through, say, all texts.)
Purely as a convenience, we can also write "member of" or "members of" in this context. For instance, in the enumerate definition, it would have been just as good to write "…running through the members of the collection…" in the repeat. (Similarly, we could write "number of members of the collection" or "a random member of the collection", which looks grammatically tidier than writing "number of the collection" or "random of the collection" – though in fact both of these do work.)
Finally, it's sometimes useful in an abstract situation to test
This condition is true if the value matches the description; the kinds must be compatible, or Inform will issue a problem message. There is no point using this for cases where the description is given explicitly:
because it is easier to write just:
So this condition is only useful when the description is stored in some variable, and its identity is not known.
Given any two kinds K and L, the kind "phrase K -> L" is now a kind. (This is meant to look like a mathematical function arrow.) For example, the phrase defined by
has the kind "phrase number -> number". Brackets and commas are used if the phrase combines several values, so
has the kind "phrase (text, number) -> text". The word "nothing" is used if there are no values in, or no value out – thus
has kind "phrase nothing -> number", and
has the kind "phrase (length, length) -> nothing".
But how are we to get at these values? The answer is that we need to give a phrase a name in order to do so. For example:
This is the same syntax used to name rules, and the idea is the same. If we try "showme doubling", the result is
The main thing we want to do with a phrase is to apply it. So:
produces
There are versions of "applied to" for phrases applied to 0 to 3 values:
This phrase produces the result of applying the given phrase, which must be one which takes no values itself.
This phrase produces the result of applying the given phrase, which must be one which takes one value itself.
This phrase produces the result of applying the given phrase, which must be one which takes two values itself.
This phrase produces the result of applying the given phrase, which must be one which takes three values itself.
So for example:
For phrases which do not produce a value, we use "apply":
This phrase causes the given phrase to be applied. It must be one which takes no values itself.
This phrase causes the given phrase to be applied. It must be one which takes one value itself.
This phrase causes the given phrase to be applied. It must be one which takes two values itself.
This phrase causes the given phrase to be applied. It must be one which takes three values itself.
Thus:
The default value for "phrase K -> nothing" is a phrase which does nothing. For example, if we write:
then S is created holding the default phrase numbers -> nothing, and if we then try it out with:
we will indeed find that nothing happens.
The default value for "phrase K -> L" is a phrase which, no matter what value of K it applies to, always produces the default value of L. (It's a sort of equivalent of the zero function in mathematics – indeed that's exactly what it is, if L is "number".) So:
produces:
Here Q is set to the default phrase because we didn't give it any other value; it has the name we might expect ("default value of phrase number -> time") and it works as advertised, producing 9:00 am no matter what number is fed in.
More ambitiously, and supposing that we have a kind called "colour" whose first possible value is "red":
produces:
When a mass of computations has to be done, the traditional approach is to work through them in a "repeat" loop. One modern alternative, growing in popularity, is to form a list of inputs; then apply the same computation to each input in turn to form a list of results (this is called "mapping"); throw out any bad or unwanted results ("filtering"); and then combine the surviving results into a single composite answer ("reducing", though some programming languages call this "folding" or "accumulation"; it's a much-reinvented idea).
Inform provides all three of these fundamental list-processing operations. There is no special term for a "map", because Inform treats it as another case of "applied to".
This phrase takes the list, applies the phrase to each entry in the list, and forms a new list of the result. Example:
Then "doubling applied to 2" produces 4, by the simpler definition of "applied to", but also:
produces the list {4, 6, 8}.
More divertingly, suppose we define:
Then we can write a chain of three maps in succession:
to produce the value {"sx", "sxtn", "ght", "thrty-ght", "frtn"}.
Next, filtering. Here we make use of descriptions, in order to say what values will be allowed through the filter. So:
This phrase produces a new list which is a thinner version of the one given, so that it contains only those values which match the description given. Example:
produces {8, 4}, with the values 3, 19, and 7 failing to make it through. A sufficiently fine filter may well thin out a list to a single entry, or even no entries at all, but the result is always a list.
To get the full effect of filtering, we probably need to define an adjective or two. For example:
We can then write, for example:
which produces the list {"fifteen", "twenty-nine", "minus four"}.
Lastly, reduction. In order to combine a whole list of values, we need a phrase to combine any two. Here are some samples:
And here are some sample reductions:
sets X to 19, the highest of the values, and Y to the text "sxsxtnghtthrty-ghtfrtn". In each case a list has been reduced to a single value which somehow combines the contents.
This phrase works through the list and accumulates the values in it, using the phrase supplied. Example: if we have
then the summing reduction of {3, 8, 4, 19, 7} is the number 41, obtained by
so that the summing phrase has been used four times.
Is map/filter/reduce always a good idea? Devotees point out that almost any computation can be thought of in this way, and in systems where the work has to be distributed around multiple processors it can be a very powerful tool. (There are programming languages without loops where it's essentially the only tool.) At its best, it reads very elegantly: one assembles all of the tools needed – definitions of doubling, lengthy, spelling out, concatenation and so on – and then each actual task is expressed in a single line at the end.
On the other hand, there are also times when this is a needlessly complicated disguise for what could more easily be done with a "repeat" loop, and also more efficiently since assembling and dismantling lists in memory does take some overhead time. So these list operations are not a panacea, but it's good to have them available.
The following looks quite innocent:
It's clear at a glance what this is intended to do, but at a second glance things aren't so straightforward. "Value" is not itself a kind – it's too big and unspecific. For instance, if we were to allow a variable to be just "a value", we could freely set it to 12 one minute and to "dahlias" the next, and such a variable would be dangerous since we would never know what could safely be done with its contents. A phrase like this one is called "generic", because it's not so much a single, actual phrase as a recipe to make phrases. (Inform automatically works out which kinds we need the phrase for, and creates a version of the phrase for those kinds.)
So "value" is not a kind, but a kind of kind. Inform has several of these:
These act as ways to say "a value of any kind matching this can go here". For example, "value" is a way to say "any kind at all"; "arithmetic value" is any kind which arithmetic can be performed on (any kind with the little calculator icon in the Arithmetic part of the Kinds index); and so on. If we write:
the restriction to "arithmetic value" means that although "double 3", "double 6 kg", etc., would be matched, "double the Entire Game" would not – you can't perform arithmetic on scenes. Similarly, it would have been tidier to write:
because then Inform will make it clearer why "say X twice" won't work if X is one of those rare values which it can't say (an activity, for instance).
The Kinds index shows which kinds match against which of these "kinds of kind". For instance, it shows that "time"
which means that time is something we can do arithmetic on, and can say.
The examples of generic phrases in the previous section were really only toy examples. Suppose we want a phrase which will take any arithmetic value and triple it. We could do something like this:
But this only prints the answer. Suppose we want to be given the value back, instead: how can we write the phrase? The trouble is that, not knowing the kind of V, we can't say what kind will be produced. We need a way of saying "the same kind comes out as went in". Inform expresses that using kind variables:
Here, K stands for any kind which matches "arithmetic value". Inform supports exactly 26 of these symbols, which are written A to Z, but it's customary to use K and L. (They can be written in the plural if we like: e.g., "list of Ks". But they must always use a capital letter: "list of k" is not allowed.)
Each symbol we use has to be declared in exactly one of the bracketed ingredients for the phrase – here, the declaration is "arithmetic value of kind K". That creates K and says that it has to be arithmetic; if we'd just said "value of kind K", it could have been anything. (Alternatively, we could use any of the kinds of kind in the previous section.)
For a more ambitious example, here is one way to define the mapping operation described earlier in the chapter:
Here we need two symbols to explain the complicated way that the values going in and out have to match up to each other. Note also the way that the temporary variable "result" is created:
Ordinarily, of course, "L" is not a kind. But within the body of a phrase definition, it means whatever kind L matched against.
When a symbol occurs several times in the same definition, subtle differences can arise according to which appearance is the declaration. These are not quite the same:
The difference arises – though very rarely – if V has some different kind compared to the list entries, but which can be used as if it were of that kind. For example,
Here V is a snippet, but L is a list of texts; and a snippet can be used in place of a text, but not vice versa. So this will match the second definition, because K is set to "text", but it won't match the first, where K is set to "snippet".
Sometimes a phrase needs to know what kind it's to work on, but isn't going to be given any particular value of it. For example:
Note that there's no hyphen, and no name for the bracketed token – it only sets K. We can then have, say:
But "assay texts" would throw a problem message, because we can't repeat through all possible texts. For a different reason,
would not be allowed – "open doors" is a description which applies to some doors and not others; it isn't a kind. It would make no sense to talk about "default value of open door", for example.
Recall the definition:
Suppose we then try to "slam shut the wall safe" at a time during play when the wall safe is already closed. An error message will then be printed during play, since there must be a mistake in the design. The combination of checking both when Inform builds the story file and then continuously when the story file is played guarantees that, in all cases, a varying item such as "box" in the definition of "To slam shut (box – open container)" always satisfies the condition laid down.
Instead suppose we also have the following definition:
We now have two definitions of "slam shut". Sometimes the box it's applied to will be closed, in which case only the second definition fits, and will be the one used. But if the box is open, both definitions fit. Which will happen? The rule is:
Rule 1 ensures that a definition involving "open container" takes priority over one which merely involves "container", for instance.
And therefore when the box is open, it's the more specific phrase to do with open containers which is invoked: so, with great panache, the box is slammed shut.
On the other hand, neither of these patterns is narrower than the other:
Some containers are transparent, some not; some transparent things are containers, some not. Rule 1 therefore does not apply, so it is the later of the two phrases which takes effect.
Another possible ambiguity occurs when a phrase might match two lexically different possibilities using the same words.
could be construed as a usage of either of these cases:
These of course have different effects – one produces the name with a definite article, the other just the name, so the difference is important.
The rule here is that whichever possibility contains the most words, in this case "say the (…)", takes precedence, because it's assumed to be a more specific form of the less wordy version.
In this chapter, we explore a number of ways to go beyond the traditional text-only, one-story-file-only model for IF.
These relatively exotic features are more demanding of the interpreter which a player uses than a plain text story file would be. They can only be used if the project is being compiled to the Glulx story file format (see the Settings panel for the project), and even then, the player will need to have a good Glulx interpreter – one which is reasonably up to date and well-written, that is – to be sure of everything working as intended.
Looking around a bookshop, perhaps half of all the books published have illustrations. The proportion may be lower for novels, but if we count maps or other occasional diagrams, even the fiction section turns out to be surprisingly pictorial. Illustrations do not suit every book, but they are an option we would like to have available.
In the cultural history of IF, graphics in text adventures have sometimes been looked at with suspicion. Mostly this is because attempts in the 1980s were not very successful, because computer graphics were so poor then (by modern standards). It may be that some people also felt that the takeover of computer games by graphical interfaces was the death knell of IF. But pictures are now rendered in superb quality by computers, and the death of IF turned out to be an exaggeration, so it is time to move on.
Whether to have illustrations ought to be an artistic choice, like whether to include a romantic sub-plot or how much of the back story is revealed. But there are practical considerations too. The most successful illustrated books are those whose pictures are well-chosen, have a sense of design to them, and above all are consistent. Consider how much worse off Winnie the Pooh would have been if a selection of random teddy-bear drawings had been used, instead of E. H. Shepherd's beautifully conceived world; or a cookery book in which the recipes are all photographed at different distances and light levels. IF writers may want to look for collaborators with a visual eye, just as most novelists do not draw their own illustrations.
Another consideration is that displaying images is more complicated for computers than displaying text. Not all devices can show pictures (consider handheld gadgets) and if they do, they may use different colour ranges or resolutions. So IF with pictures is always just a bit less portable than IF without, and because of that we must next look again at IF story file formats.
Back in Chapter 2, we saw that the Settings panel allows any given Inform project to be produced in either of two possible story file formats. Recall that story files are the released IF works: what the player sees. The source text, the Index, and so on are not part of this.
A story file is not like a word-processed document, or a photograph. There are many rival formats for these – for instance, an image on a web page might be in JPEG or PNG format, among many others – but basically they are simple things for the reader to look at, and see everything in one go. An IF story file is more complicated, because the "reader" reacts to it, types in to it, is surprised by it, never quite knows what might happen next.
A story file is in fact a computer program in its own right, but not a program like iTunes or Firefox which runs on a typical home or business computer. Instead it is a program for an imaginary computer, called a "virtual machine" or "VM". This has a design ideally suited to IF, and it would be the perfect IF player's computer if only it actually existed. Because it doesn't, the player instead runs an "interpreter" program like Windows Glulxe or Zoom or Spatterlight – and this one is a program like iTunes or Firefox – and the interpreter acts as a middle-man. It creates a software version of the virtual machine, and then runs the IF story file on that VM. This sounds slow and impractical, but in fact it works well, and is also much safer since programs on the VM are not allowed to touch the real computer – so they cannot at all easily contain viruses or other malware. (In theory a malicious story file might try to exploit a bug in one of the various VM implementations in use, just as malicious image files have been used to attack bugs in web browsers, but this has never in practice happened. Nothing can be absolutely safe, but a story file belongs in the "mostly harmless" category of files – like images – rather than the "how far do you trust this person?" category – like programs.)
The different formats of story file are programs for different virtual machines. Just as Windows and Mac OS X offer basically similar services to the user but are very different in appearance and their workings, so the different VMs are quite different. Some can display pictures, others not.
Inform provides basic support for displaying pictures and leaves more exotic effects for Extensions to provide. But either way, for reasons explained in the previous section, we can only have pictures if the Settings for the project are set to the Glulx story file format.
Inform calls these pictures "figures", following the usual Inform analogy with books. We will think of our work of IF as being like a mostly textual book which in broken up with illustrations here and there – Figure 1, Figure 2, and so on. These might be used to mark each new chapter of the plot, or each new location: whatever the author would like. So the first thing we need to do is decide when pictures should appear.
The second thing to do is to get hold of the pictures we want to use. These might be photographs, or artwork, or diagrams: anything, really, but we will need them to be in either JPEG or PNG format. Inform does not itself try to be an image editor, or an artwork program – there are many such programs already which do these things much better than Inform could.
The pictures then need to be put in a special place where Inform can reach them. Suppose the Inform project is called Example.inform. Then we need to create a folder alongside it called "Example.materials", and create a further folder inside that called "Figures". The actual images go inside "Figures". So we might then have files like so:
The ".materials" folder for an Inform project will turn out to have many other uses in the chapter on Publishing, and will be explained further there.
Inside Inform, the source text for a project always tries to avoid talking about filenames – we need a better way to refer to the individual figures.
We do this by declaring each figure with a sentence like the following examples:
Figure names can consist of any text provided that text starts with the word "Figure". So "Figure 3 – Woodlands", for instance, or even "Figure W" would have been just as good as "Figure of Woodlands". Books tend to number figures, but then, in a book the order in which they appear is known in advance – which might not be true in IF.
The file names must be exactly those used in the Figures folder. We need not declare every image kept there, but those we don't declare – remember Blackberry.jpg? – cannot be displayed.
We can preview the stock of figures by going to the table of figures in the Contents index for a project (once the project has been built, that is, so that its index is up to date). This preview shows thumbnail forms of the pictures, the names, the formats and the image sizes in pixels. A warning triangle is shown for any images in the wrong format, or which are missing from the Figures folder.
Inform's basic picture support simply allows figures to be shown at particular times. Once seen, they scroll away, just as text does once it has been printed. These pictures are really part of the stream of narrative. (If we would like icons or other images to be permanently present on screen, and divide the screen up in pictorial ways to achieve interesting layouts, we need to use special extensions to access Glulx's more exotic features.)
Displaying a picture is therefore like printing some text. Rather than
we would use:
This phrase causes the figure to be displayed in a way visible to the player. If the option "one time only" is used, it will have no effect if the figure has been displayed before. Example:
Once again, note that the "display" phrase does nothing unless the Settings for the project are set to the Glulx story file format. When a Glulx work is released as a blorb (the default setting for the way releases occur: see the chapter on Publishing), all the images used are automatically included.
Inform also supports the playing back of recorded sounds, which might be anything from a three-second sound effect for a creaking door to an epic orchestral symphony. Sound support is very newly added to the system and work is still in progress. In particular, sounds are not played by Inform for OS X (although it does produce valid blorbed Glulx story files), though they should be audible from within the Inform application for Windows.
Once again, sound effects are supported by Inform 7 only on the Glulx platform, and even then we must be prepared for the fact that not all interpreters will be able to play them back. We must also bear in mind that a sound recording is a large pile of bits, and that adding any kind of sounds will greatly increase the size of the Blorb file for the released Glulx story file.
The sound files provided must have one of two formats: AIFF or Ogg Vorbis. AIFF is a traditional format in the recording industry, though it is more familiar to Mac OS X users than Windows users. It is uncompressed, giving what can be excellent audio quality, but at the cost of sometimes enormous file sizes – perhaps as much as 10 MB per minute, though this can be greatly reduced by lowering the sampling frequency, and halved again by dropping from stereo to mono.
Except for very short sound effects, we recommend using Ogg Vorbis instead. This is a compressed format whose file sizes will typically be more like 1 MB per minute. Inform uses Ogg Vorbis as the only format safe from licencing and patent disputes. (We would very much have liked to provide MP3 support, but this is no longer legally possible for free software.)
Support for Ogg Vorbis is not built in to either Windows or Mac OS X, and any sound recording you make will probably have to be made first to another format (perhaps AIFF or WAV), and then converted. See xiph.org/vorbis for encoding software which can convert from other sound formats to Vorbis.
Lastly, it must be remembered that recording industry bodies are very hostile to established copyright law covering fair use, parody, quotation of insubstantial passages, etc., when it comes to mixing or using commercially released music. They are well-resourced and highly litigious. If you use sound effects not originated by yourself, you do so at your own risk, even if what you do is perfectly legal on any reading of the statutes.
Sound effects are accommodated on the same basis as illustrations. The relevant media files need to be placed in a subfolder of the project's ".materials" folder, but this time called Sounds rather than Figures, so for instance:
Again, these must be declared in the source text:
And they can be played using a special phrase:
This phrase causes the sound effect to be played. If the option "one time only" is used, it will have no effect if the sound effect has been played before. Example:
It's conventional for web pages to provide "alt-text" for significant images displayed, so that partially sighted or blind users can get an idea of what is being shown. Inform allows figures to be given these short descriptions like so:
As we'll see, the same can be done for the cover image:
And also for sounds:
(i) Names for figures, such as "Figure of Woodlands", are values for a special kind of value called "figure name". This can in turn be used to define variables, properties and phrases:
(ii) Similarly, names for sound effects, such as "Sound of rustling leaves", are values for the kind of value "sound name".
(iii) In the released, blorbed-up Glulx file, figures and sound effects are internally given resource ID numbers which count upwards from 2 in order of their declaration. (Figure and sound numbers can thus be intermingled, if their declarations are.) Resource ID number 1 is reserved for the image of the cover art, if there is any. (See the chapter on Publishing.) To obtain these numbers, if we need them, we can use:
This phrase produces the ID number used in the eventual Glulx file for the given figure.
This phrase produces the ID number used in the eventual Glulx file for the given sound effect.
(iv) Glulx hackers may also like to know that whenever Inform 7 builds a project for Glulx, the Inform 6 code it generates always contains a full copy of John Cater's definitive header file "infglk.h".
Once an Inform project is released, it is playable as a "story file", which is in effect a computer program for a specially IF-adapted design of computer. Story files run in what in computing is sometimes called a "sandbox", a kind of safe play area where it can be guaranteed that they cannot do any harm. This is good, because it means a story file can't be infected with viruses or other malware. If the project's Settings panel has the story file format set to the Z-machine, the story file is so thoroughly boxed in that it cannot even see the bigger computer beyond: it lives in a world of its own. But the Glulx format opens the door a crack, allowing the story file to read and write a small number of data files, which live in a single folder on the bigger computer's hard drive.
Why might we want this? Among the reasons are -
Like figures and sounds, files must be declared before they can be used. For instance:
This creates a new named constant "File of Glaciers" to refer to the file, throughout the source text. We use this name for it whether or not the actual disc file exists yet: it might be one that will only be created if something unusual happens in play, for instance.
Quoted filenames should contain only letters and digits, should be 23 characters or fewer, and should begin with a letter. (In particular they can contain no slashes or dots – no subfolders or extensions can be indicated.) The actual filename this translates to will vary from platform to platform, but "ice.glkdata" is typical, stored in some sensible folder.
Every file has an owner – not a person, but the project which normally writes to it. Inform assumes that the current project will be owning any file which it declares – the File of Glaciers, for instance. But we can optionally specify that it is owned by somebody else:
Inform uses ownership to make sure that we do not accidentally read in a file which has nothing to do with us, but merely happens to use the same name. Thus it is an error to read a file whose ownership does not agree with our declaration. Saying that a file is owned by "another project" allows us to read it whatever the owner is (so this can be used for files shared between multiple projects); specifying exactly where it needs to come from allows us to pass information from one project to another. Note that we identify projects using the IFID number – this can be found in the Contents index for a project, or by typing VERSION during play; see the chapter on Publishing for more about IFIDs.
Files are indexed in the Contents index, alongside figures and sound effects.
Two technicalities. First, constants such as "File of Glaciers" are of a kind of value called "external file" (compare "figure name" and "sound name"). Second, Inform's file-handling is provided for the Glulx machine, which in turn uses the Glk interface. This allows for either text or binary files. Inform's higher-level phrases to do with files, described in this chapter, all use text files, and all declared files are text files by default. But we can optionally add the keyword "binary" to declare a binary file, if needed:
The main use for files is to store and retrieve data, and the most flexible form of data used by Inform is the Table, so facilities are provided which make it as easy as possible to write and read the contents of a table to files. If so, the file must contain just one single table: so to write multiple tables, we need to write multiple files, one for each.
To save the contents of a table to a file, we use the phrase:
This phrase causes the entire contents of the given table to be written out to the given file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:
Any blank rows in the table are automatically moved to the bottom, and only the non-blank rows are written.
To load a file back into a table,
This phrase causes the entire contents of the given table to be read in from the given file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:
Any rows left spare at the foot of the table are automatically blanked. On the other hand if the file is too large to fit into the table – with too many columns or too many rows – a run-time problem is produced.
We can check if a file already exists using:
This condition is true if the file-system used by the player appears to contain a file with the right name. For example, if we declared:
and then tested
then Inform would search for a file called "icedata". (The arrangements for where this might be stored, and its filename extension, vary from platform to platform.)
One unfortunate restriction must be kept in mind. Some of what is stored in tables is solid information whose meaning never changes: the number 342, for instance, means the same to everyone. But other information depends entirely on the current location of certain structures in memory – for instance, a rule is internally referred to by its memory location. This potentially changes each time Go or Replay is clicked, and so it is not safe to pass it from one copy to another, or from one project to another. The only tables which Inform allows us to write into files are those containing "safe" data: numbers, units, times of day and kinds of value with named alternatives. Scenes, rules or rulebooks, in particular, are not allowed.
Text can also be saved to a file, and again all file-handling is automatic:
This phrase makes the given text become the entire contents of the named file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:
This phrase adds the given text to the end of the current contents of the named file (creating it if it does not exist on disc). Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:
The quoted text can, of course, contain substitutions, so can be long and complex if need be.
Text from a file is printed back with the text substitution:
This text expands to the contents of the named file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example:
To copy one file to another, for instance,
Provided we declare the files in the right way, it is easy for one project to read a file created by another project.
But if we want more rapid communication, between two projects which are each playing at the same time, we need to be more careful. What if project A tries to read the file at the same moment that project B is writing it?
To avoid this, we have a concept of files being "ready". A file is ready if it exists, and is completely written, and not in use elsewhere. We have already seen:
But now we want a stronger condition:
This condition is true if the file exists and is marked as being ready to read; that is, it is not in a state where another program is currently writing it. Example:
A file cannot be ready to read if it does not exist, so this is a stronger condition. If A and B are attempting communication in real time, both running at once, then Project A should check that an external file owned by B is ready before it tries to read it. Files can also be marked as ready or not ready, in effect claiming them, thus:
This phrase marks that we have finished writing to the given file, so that any external program is welcome to read it now. Example:
This phrase marks that we are about to start writing to the given file, so that any external program should wait until we're finished if it wants to read the file. Example:
Possibilities really begin to open up when project A is our story file, but B is not another story file at all: it is some external program such as a Web service, say. (Of course this is harder to set up, since the player needs to have both A and B running at the same time, but for stories running on an Internet server this can all be made seamless.)
When Inform begins writing a table, or text, to a file, it initially marks the file as not ready: only when the table or text is completely written and the file about to close is the file marked as ready.
In order to write non-story-file programs as B, communicating with story files as A, we need to know the file format used by Inform. An Inform file is currently a Unix text file (with 10 as the line division character), encoded as ASCII Latin-1. (We would like to use Unicode at some point in the future, but the Glk and Glulx layers are still not fully converted to Unicode.) It opens with a single header line in the form:
The opening character is an asterisk if the file is currently ready, a hyphen if the file is currently not ready. The IFID between the slashes is the IFID number of the project which last wrote to the file. (Marking "ready" or "not ready" does not count as a write for this purpose.) If an external program wrote the file, it should call itself something which will not clash with any story file's IFID. The leafname is the filename text used inside the story file where the file was declared. For instance:
Testing a story -- and indeed writing a story so that it is easy to test consistently -- is an art in itself. We should expect that we'll do some preliminary testing, both by running test commands and by playing through the story ourselves, and that we'll then hand on the story to beta-testers who will tell us about faults in the play experience that we haven't been able to see.
Every time Inform builds a new story file, it assembles a vast amount of information about that world, in the form of the Index. Often a visit to the Index is all that's needed to explain a piece of undesired behavior.
Is travel not working as it should? Check the World index and see whether the map shows the rooms arranged the way you thought.
Are objects not showing the behavior you'd expect based on their kind? Check the Kinds index and make sure they've been defined as the kind of thing you expected. For instance, we might find that we've written
but not
A human reader wouldn't make this mistake, but Inform hasn't actually registered the red door as belonging to the door kind, and consequently has treated it as a room instead. All we need to do is add the kind declaration. The Kinds index will make that obvious.
When an error appears in the Index, there is often a link back to the source text that defined that room or object. If not, there's often at least some information about what rule or phrase might be responsible for it.
The TEST command is an extremely useful way of managing a story and continuing to verify that it does everything we want. We can create new test commands of the form
and we are free to have as many of these tests as we would like. Test commands can call other tests, as well, so we might have a test command such as
A word of warning: if the first command in the test is "again", that will likely repeat the TEST command, sending Inform round in circles forever.
For complicated objects and commands, sometimes it's a good idea to develop the test commands at the same time that we're writing the source code itself. Each time we add a new rule or piece of behavior, we also add to that object's special test command something that will put that new feature to the test. This means that we can keep running the test command as we work and verify that everything is behaving as expected.
Sometimes we need to get a look at what is happening within the source itself. Many of the most annoying bugs come about because we're making some assumptions about what's true in the story world that differ from Inform's assumptions. When that happens, we may need to add something to the source to check that the variables are set to what we think, that certain parts of the source are being reached, and so on.
For instance, suppose we have a phrase like this:
Now, we expect this to print something, but perhaps it's not doing so when we had anticipated that it would. At some point when we think the count is greater than 2 and the player is timid, at least one of those things is not true. An easy way to check up on this is to add a showme line to the source, like so:
and this will then check the relevant number and print it to screen when this phrase is called, like so
In this case, it looks like the count is not high enough to trigger the text, so we can concentrate on working out why that might be. Maybe we didn't correctly define something as a key, for instance.
If an object is not responding in the way we expect, it may be that we're wrong about where it is or about some of its current properties or relations. We can find our current location and the things around us by typing
and similarly we can inquire about the status of a particular object during play by typing SHOWME and the object's name:
This will work even if we're not in the same location as the object we want shown.
Another common type of problem is one in which we type a command but Inform does not perform the action that we were expecting as a result. In some cases, this is because the command we're typing is actually triggering some other action. An easy way to check on this is to type ACTIONS before issuing the command that is behaving unsatisfactorily. Thus:
This tells us how Inform interpreted our input and whether the action was successful or failed for some reason. If the command is being understood as a different command than we expected, that may mean that we have made a mistake in our Understand instructions, and need to double-check these.
Sometimes, however, the action is being correctly understood, but the action rules that are firing are producing a result other than we'd like. If we want to see which rules are running, we can type
As we can see, RULES produces a lot of output, much of which is probably irrelevant to whatever problem we're tracking down. Nonetheless, knowing exactly which rule is printing undesirable output is helpful, especially if that rule comes out of an extension or some other source that we did not write ourselves: this output has told us that the text we saw came from the "report jumping rule".
To find out more about what is going on in specific rules, we can also turn to the Index tab under Actions and click through to that specific action. From there we will be able to see which rules are included, what responses they're writing, and where they were defined in the source text.
SCENES lists which scenes are currently playing and which are complete. This is valuable if scene-triggered events are not happening when we expect them to.
RANDOM sets the random number generator to a predictable seed. If we include this in a test command, it will guarantee that the subsequent behavior of the story is consistent across multiple playthroughs, which is helpful if we're trying to test something to do with, say, randomly wandering non-player characters.
RELATIONS lists all the relations defined in the story, except for things like support and containment that are part of the world model and are so numerous that the output would be overwhelming.
RESPONSES lists all the named responses established by all the extensions currently included. This can be informative, or it can be a bit overwhelming. Except where responses have been changed at runtime, the same information is available in a different form in the Index on Actions. If we're interested in a particular single response, digging into the actions index is probably the easiest way to find it.
If, however, we want a rapid overview of all the responses provided by a given extension (perhaps an extension we are ourselves writing), the RESPONSES command can be a help.
There are also several debugging commands going back to the early days of interactive fiction, and relating in a simple way to objects and places. These can still come in handy for a quick and dirty resolution of a problem during gameplay, and are as follows.
PURLOIN moves an object to your possession, no matter where it is on the map, like so:
Note that purloin does not consider the usual rules about whether something can be taken. In this case, we've just moved the table to our inventory even though it is a fixed in place supporter that could not be taken in the normal course of events.
Because purloin works on things that are far away as well as things that are close, it has to do a lot of extra parsing work and may take a moment or two to complete if we try it in a very large story. It is generally more efficient to give the player the relevant object using a testing command, like this:
Nonetheless, there are occasionally times when we're halfway into a 2000-move story and suddenly realize we implemented a vital object in the wrong room, making the story unsolvable. We could fix the bug, press replay and return to this story state fairly quickly, but if we don't feel like waiting even that long, PURLOIN will resolve the issue.
ABSTRACT is PURLOIN's less useful cousin, allowing the player to move an object from one place to a specified other place, as in
GONEAR transports the player instantly to the vicinity of the named object, so for instance
As a debugging command, this isn't protected in the ways that commands usually are. It's possible to type GONEAR NORTH and produce a run-time error when Inform tries to move the player into the object that represents the compass. Again, except in cases where we're tracing a problem very deep in an already running story, it is usually more practical to write a test command to put the player in the correct situation, as in
VERIFY checks that the story file is intact rather than damaged, but it is hard to think of an occasion when this would be likely to arise within the Inform application. The command is a holdover from a time when data transfer was much slower and more error-prone, and it was plausible to have a story file of just a few hundred KB corrupted during transmission.
TREE creates a list of object containment. It is similar to SHOWME, but less elegant and thorough.
SCOPE lists the objects that are currently in scope for the player, which is to say, things that could be referred to when we're typing a typical command. Thus:
The following numbers are object IDs for these objects, which can distinguish items with identical names. It is likely that the output of this will not be terribly interesting or different from checking SHOWME, except in cases where the author is deliberately changing the scope to be something other than "the set of things that are visible in the room with the player right now". This usually involves the Deciding the scope of something activity (see the chapter on Activities).
SHOWHEAP shows how many bytes are currently free. This is usually not helpful.
SHOWVERB (verbname) lists the Understand information associated with a particular verb. Similar information, in a vastly more palatable form, is available in Index / Actions / Commands, so the one time SHOWVERB becomes useful is when Inform is considering the understand lines in the wrong order and producing a result we didn't want: SHOWVERB will show us the order in which the lines are being assessed. The challenge will then be to add conditions to the Understand lines to move them into the correct order.
Finally, TRACE (and its more advanced stages TRACE 2, TRACE 3, TRACE 4, and TRACE 5) will reveal things, more things than we ever wanted to know, about the assumptions being made by the parser when it takes in a command. In practice this information is almost never useful to an Inform 7 author.
There is no guarantee that any of these commands will make life better or that they won't crash the story or put it into an unwinnable state. There is also no absolute guarantee that they won't be withdrawn entirely from future versions of Inform. Consider them as Old High Magic, and treat accordingly.
As we saw in Chapter 2, we can mark some of our source text so that it will not be included in a finished story. This means that we can add special testing commands available to the author but not available to our eventual players. This is a good way to add our own suite of testing verbs to a story beyond the "Test me with…" features already described.
Here are some types of testing verbs that can be useful to add:
Chapter jumps. We might create test commands that took us to a later stage of the story (perhaps doing more setup than "Test me…" alone can handle).
Status information. We might create a test command that would show us status information beyond what's covered in the Standard Rules. For instance, if we had a story that heavily modeled the moods of other characters and we wanted to be able to check those moods at any time, we might add a SHOWMOOD command that would tell us about a character's emotional state.
Puzzle satisfaction lists. Some simulation-rich stories offer puzzles that can be solved in a variety of ways: for instance, a sealed glass box that can be smashed with any object that has been marked with the properties "hard" and "heavy". Later, we might want to be able to check which in-story objects would work as a solution to this puzzle, so we might create a command like
so that we can review that there are enough objects available and that the list doesn't include anything it shouldn't. In a small story this kind of thing is pretty easy to keep track of in the author's head. Large stories can contain thousands of objects, however, at which point it becomes valuable to have an automated method of verification.
Just occasionally, we might also want to build a version of a story that will allow beta-testers access to the debugging commands. This is especially relevant for long stories: if we're testing a story with a lot of playtime and the testers have already thoroughly reviewed the first portion of the story, we might want to let them have access to testing commands that fast-forward to later sections.
To do this, we can use the "Release for Testing" feature. Release for testing builds a version of the story that does include testing commands and any sections labeled "Not for release".
The presence of actual bugs or defects is not the only thing we want to consider when testing a story. We may also want to check whether we have built the story with a consistent amount of depth.
Are there descriptions for everything the player might look at? If we've implemented special verbs, do they have appropriate reactions for all the different objects? If most objects in a story about restaurant reviewing have a special response to being tasted, for instance, it might be disappointing for the player to encounter late-added objects that don't.
Checking implementation thoroughness can be a laborious process, but there are a few things we can do to automate it. For instance, we might add to a not-for-release section a rule that checks for certain properties:
This will confront us with a reminder of what we still need to fill in every time we start up the story.
There are also some extensions that are designed to assist with this, notably the massive Object Response Tests by Juhana Leinonen. Object Response Tests allows us to try out a long list of commands against any object in the story, so that we can quickly identify ones with nonsensical replies.
Inform includes a command that is especially designed to help beta-testers report flaws: namely, TRANSCRIPT. A tester can type TRANSCRIPT (or just SCRIPT) at the beginning of the story in order to start generating a recording of everything that happens. She can then add her own annotations when something buggy or otherwise notable occurs (for instance by typing a standard symbol, such as *, followed by a note).
When she then sends us the completed transcript, we can look through for these symbols and note the problems the tester found in the context of the rest of the story's behavior. Having information about how she reached that position typically makes it much easier to reproduce the problem than if she gave only a general account of it.
Sometimes we get really stuck on a problem and despite all our best efforts cannot figure out how to solve it.
Fortunately, Inform has a lively and helpful community of users who are often willing to assist other authors. The easiest way to reach these users is to make a post at the intfiction forum at
and in particular to post Inform-related problems under the topic Inform 7 Development. Where possible, it's a good idea to post the example source that is causing trouble, and to make it as short as possible so that prospective helpers will not have to read any more than necessary in order to pinpoint the problem.
The user community is also a good place to find beta-testers who can try out our work and give feedback.
This chapter and the next are about what to do when we have a complete, finished work on our hands.
For almost all of the time when a new work of IF is being written, it lives inside the familiar two-panel spread of the Inform user interface. But that isn't how eventual players will experience it. They will want to play a "story file" in a standard format, and they will do so with a wide range of different interpreters on many different computers or websites, including some -- like mobile phones -- on which Inform itself will not run.
So how does a new work of IF reach players? The simple answer, covered in this chapter, is that clicking the Release button instead of Go causes Inform to output a stand-alone story file. But as we will see, Release can do much more than that: it can attach covers, include bibliographic data, make websites and much more. Releasing is the process of making all of the material we want to deliver to our eventual players.
But that is only the first step. What do we do with the material when we have it? Printing out a manuscript of a novel is not the same as publishing it. So the next chapter, on Publishing, completes the story.
Almost all printed books have a title page and a so-called "imprint" page, often its verso, which make up a description of the contents. The title page gives the name of the book and of the author, while an imprint page contains a variety of details about the edition, the printing, and so on. An ISBN number is allocated so that, from the number alone, any book seller or cataloguer can identify exactly this work. Sometimes other cataloguing information is added, such as the Library of Congress classification. This set of information is called "bibliographic data", and without it libraries and booksellers would be at a total loss.
IF has bibliographic data, too. Inform has a number of special named values to hold this – who wrote the work being created, what it is called, what headline it has, what genre it has and what its release number is, and so on.
These can be set as follows:
Most of these are self-explanatory. The "story creation year" is provided so that if we need to revise the work to fix some bugs a year later – by no means an uncommon occurrence – then we can make sure it is correctly identified as still being basically a 2005 work. (Just as a book which has had innumerable revised printings may say "First published 1988" on its imprint page.) The "story description" is a piece of text, analogous to the back cover blurb on a book: it might be two or three paragraphs long, so the example above is rather minimal, but it should not be epic in length.
As we have already seen, a convenient abbreviation provides that if the first sentence of the source text consists solely of text in quotation marks, then that is considered the title. Thus if the source begins:
then that will be the "story title". Further, we can write
with the obvious effect: quotation marks around the author's name are optional here, for convenience, but note that we'd better have them in cases like:
as otherwise the full stop after the K will end the sentence prematurely.
The text of these bibliographic descriptions cannot normally include text substitutions, since they are written into external descriptions of the story file as part of its "binding". Two exceptions are allowed, though: "[']" makes a literal apostrophe, and can be used if we need to override Inform's normal conventions to do with converting apostrophes at the ends of words to double-quotes. For instance:
The other exception is that the "[unicode …]" text substitution works, so for example:
If the bibliographic named values are not set by the source text, Inform will still need to say something. Unset text and number variables evaluate to "" and 0 respectively, but this would make for a very unhelpful record. So Inform uses the following table instead of any value which is unset:
The "story genre" is not used in the banner at all, and exists purely to help librarians. If it is at all possible to do so, authors are asked to use one of the following standard categories:
These categories are based on those currently used by bookshops, but a few notes may be helpful. "Fiction" is intended for works whose essential purpose is literary, in a way which trumps any subject they happen to have: if Julian Barnes writes a mystery, for instance, a bookshop will shelve it with modern novels rather than in the detective stories section, whereas P. D. James's Adam Dalgliesh mysteries will end up filed with detective fiction even though she has appreciable claims to be an important novelist.
"Comedy" is used rather than "humour" to avoid the clash of spellings with "humor". This genre includes parodies.
"Non-Fiction" would be used for a work of IF which is essentially a presentation, perhaps in a novel interactive format, of true information. A meticulous simulation of the Great Exhibition of 1851, for instance, might qualify.
The distinction between "Surreal" and "Other" is that "Surreal" works contain at least some semblance of narrative, whereas "Other" is intended for works which "abuse" the format to present some entirely different sort of game – Tetris, say, or Minesweeper.
Bibliographic data is useful for two reasons. Firstly, it enables the equivalent of a title page to be printed – traditionally called the "banner" – at the start of play; secondly, Inform uses it to generate the equivalent of a library card for the work, which can be used by other programs to help organise, sort and classify interactive fiction. If the card is given to any other program on any other machine (or an Internet-based archive) then, in principle, that system can know about our work of fiction without a human librarian having to get hold of a copy, play it and laboriously copy out the details.
The "library card" is not of course a physical card, but a small "metadata" file which could potentially be transmitted quickly across the Internet. It contains no personal data other than what you choose to put on it, using the sentences documented in this chapter: it does not, for instance, identify your computer or IP address. In any case Inform does not send it anywhere, but merely keeps an up-to-date copy within the project, and includes it when making a release copy of the work. You can always see (a representation of) the current library card for a project in the Contents index.
Authors are asked to play fair, in return, by writing sensible and useful bibliographic information for any work which is likely to circulate to other people; by being honest (writing under a pseudonym is fine, but not impersonating other people); and by conforming to standard practice.
The Settings panel of each project contains a tick-box called "Bind up into a Blorb archive on release", and by default this is ticked. "Blorb" is a nonsense word from a popular early 1980s work of IF called "Enchanter", where it was the name of a magic spell whose purpose was to "safely protect a small object as though in a strong box". In the late 1990s, the name was borrowed for a standard format for what might be called the wrapping and packaging of IF. A typical Blorb archive produced by Inform contains the "story file" – the actual program for the story – together with its library card and cover art.
Modern IF interpreters such as Zoom for Mac OS X and Unix, and Windows Frotz, can play blorb archives directly, and the authors of Inform hope to make this the normal practice in future. Still, some interpreters cannot read blorbs directly and have to be given the actual story file: so by unchecking the above tick-box, we can insist that Inform creates only that. The disadvantage with this, of course, is that the library card (with all its bibliographic data) and any cover art is lost in the process.
During March and April 2006, an agreement was reached between the IF archive and most of the different systems for creating IF – of which Inform is only one – called the Treaty of Babel. While these different systems create computer programs which are quite different internally, the Treaty provides for works of IF to come with bibliographic data which identifies them in a standard way.
Inform is fully compliant with the Treaty. In particular, each new project created by Inform is allocated a unique identification number called its IFID. The IFID is the equivalent for IF of the ISBN of a printed book. Inform copies it onto the "library card" for the benefit of Internet-based libraries which may eventually accession the work. Of course many projects start but never see the light of day, so many possible IFIDs are "wasted": but that hardly matters, as there are plenty more numbers in the world.
The important thing is that
Inform will make sure this is true, unless we do something to break this ourselves. For instance, if we take an existing project, copy it as a file, then work divergently on the original and on the copy so that they become two radically different works, they will still each have the same ID. This is a bad thing: if we want to duplicate a project but then turn it into something new, the best way to do that is to create a new project, and to copy and paste the source from the old to the new.
Inform's Release button does two things: it makes a stand-alone, public version of the current project – a "story file" – and it gathers up, or creates, whatever material we want to go with it.
The release version of the project can be played by anyone with an "interpreter" – they do not need the Inform application installed on their computers, and they will not be able to see the source text. Released versions differ slightly from the versions playable in the Story panel of Inform, because debugging commands such as ACTIONS are not included with them. (As we've seen, also excluded is any material in the source text under a heading including the words "not for release".) In some cases, if we release along with an interpreter, we can even make the project playable from a web browser, so that the player doesn't need to install any software at all, not even a browser plugin.
The Release button also creates a ".materials" folder for the project, if one doesn't exist already. (On some platforms, the Inform user interface creates it automatically alongside the project.) Inform adopts the following convention:
For example, if we have a project filenamed Magician.inform which lives in a folder called "Works in Progress", then files might be arranged like so:
Of course "Magician" might not actually be the title of the project – it might be an abbreviation, or a working title. The name of the .materials folder has to match the name of the .inform file, not the title.
Several advanced features of Inform make use of the materials folder, and the "Release" button is one of them. It creates a further subfolder called "Release" within the materials folder. This is where it will always place the story file it creates, together with anything released "along with" the story – Inform will not need to put up a dialogue box asking us where to save the story file, because there is already a natural place. For instance, after a successful click on Release, we might then see:
where "Magician.zblorb" is the actual story file produced by Inform. Note that Inform has made copies of the files to be released with it – the idea is that the Release subfolder contains only what Inform makes, and everything in the Release subfolder can be thrown away at any time.
This is especially useful if we're releasing along with a website (see below), as then the Release subfolder will be exactly what needs to be uploaded to a server to be shown to the world. Equally, the Release subfolder is what can be zipped up and uploaded to archives or (if small enough) emailed out.
"Feelie" is a slang word, again going back to the early days of IF, for something tactile included with commercially sold copies of IF games. For instance, Infocom's "Wishbringer" was not just a diskette in a pretty box: the box also contained a map, a letter, an envelope, a magic stone (well, a stone) and a booklet. Most of this was purely for fun, and to flesh out background to the story, but there would usually be clues sneaked into the text or artwork as well.
Today's IF is usually not supplied in physical packaging, and not accompanied by physical objects. But authors do sometimes want to include extraneous matter, whether it's a simple read-me file of instructions or a multimedia extravaganza. Inform does not provide facilities to make artwork, movies, soundscapes, booklets, etc.: there are plenty of programs out there to do all of that already.
But Inform does help with the collation and packaging-together. For instance, by placing the following sentence in the source text:
…we tell Inform that we will also be providing two additional files. Note that in each case we supply a brief description and a filename. The filename should always have a standard file extension for a well-known and thoroughly standardised file format – ".pdf" and ".mp3" are pretty safe: so for instance are ".txt", ".png", ".jpg", ".html". The filename should not include punctuation marks other than the full stop dividing name from extension, and should not exceed 30 characters in length.
It is also possible to supply a feelie which is not a single file, but is a mini-website: that is, a collection of interlinked HTML (and perhaps other) files. The convention here would be:
The absence of a file extension on the filename "Guide" tells Inform that the feelie in question is a mini-website: it is expected to sit inside a folder called "Guide", with its home page being "Guide/index.html". However, a mini-website like this must be created by hand: Inform does not copy it into place, it only creates links to the place where it ought to be put.
We have seen that Inform takes the story file, which is analogous to the pages of a book, and places it into a Blorb archive, analogous to the binding. These new additional files are not placed in the Blorb, because that would make the Blorb archive rather large (and would hide them from the player, which defeats the purpose). But references to them do appear in the Blorb, so that any interpreter playing the Blorb would be able to tell that there are supposed to be additional files available. Similarly, references are entered onto the library card.
Accompanying files are not the only things which can be included in a "release along with" sentence: for instance, we could
Cover art can not only be used to advertise a work of IF, it is also displayed to players by certain interpreters, such as Zoom or Spatterlight for OS X, or Windows Frotz for Windows. It is also used on the IFDB (ifdb.org), and by browsing applications. If Zoom is installed, then on Mac OS X Leopard, the Finder shows cover art directly:

Cover art for a work should be prepared in either JPEG (".jpg") or PNG (".png") format, and we recommend that it should be square, like a music album cover. Programs which notice the cover art for a work of IF are likely to scale this up or down as convenient for their own display purposes, but it would be helpful to provide the original art at 960 by 960 resolution. The cover art must not be smaller than 120 pixels in either dimension.
To provide cover art, we should create an image file called Cover.jpg, or else Cover.png, and place it in the project's .materials folder. For instance, we might have:
(supposing that, as in the previous examples, "Collegio.pdf" and "Mating Wyverns.mp3" are the filenames of two feelies that accompany the release).
The text in brackets after the release instruction…
…is provided for the benefit of blind or partially sighted users, and should be brief.
When IF is aimed particularly at people who have never played IF before, there are certain conventions which it's a good idea to explain, or players will simply not know what to do. It can become a chore writing a clear set of instructions, and then there is the further nuisance of explaining about the need for an interpreter program to play the IF story file.
To alleviate this, Inform can "Release along with an introductory booklet", as for instance in this example:
The introductory booklet is a standard 8-page PDF file, written and designed by Emily Short, which contains all the basic information needed for a player to get started. It has been written to be as general-purpose as possible, in the hope of being useful for a range of widely different works of IF. There will certainly be works to which it would not be an appropriate supplement, and some authors will certainly prefer to write their own notes for players, but of course it is not compulsory. By making it available as a convenience, the authors of Inform do not intend to say that these are the "official" instructions or that others are not. It is simply intended as a time-saver.
As an alternative, or a supplement, it's also possible to:
which supplies a standard postcard about IF (everything new players need to know, at one glance) written and designed by Andrew Plotkin and Lea Albaugh.
Much of the published IF of the last twenty years came with a brief text file describing what it was – a release note. Today it makes more sense to write this as a small web page, which can either be placed online, or simply distributed as part of the release.
Inform is able to manufacture such a website automatically. We request this by writing, for instance,
where the list of ingredients now includes "a website". In fact, Inform makes only a single web page, called "index.html", which it places in the materials folder (as set up in the previous section): this then contains suitable links to all the other material, such as the cover art images, if they are also provided. For instance:

After a successful release now, then, we should see:
("Release/Small Cover.jpg" is a form of the cover image intended for display at a smaller size. In earlier versions of Inform, the author had to provide this: there is now no need.)
Modern web browsers are now so powerful as computing environments that they almost amount to general-purpose computers in their own right. The websites made in the previous section were passive, and simply displayed information about a story file. But it's also possible to make a more active page – one which can play the story file, right inside the browser, for anybody who visits.
To make such a page, we must:
This automatically releases along with a website as well, since we need the website in order to house the new page, which will be called "play.html". This page will be bundled up with a customised copy of a story file interpreter coded in Javascript – in effect, a program for a web browser to follow – and a suitably encoded version of the story file. The practical effect should be that anyone visiting the page with any modern browser can just play.
Inform ships with the "Parchment" and "Quixe" interpreters built in. By default Inform will use Parchment if the format (on the project's Settings panel) is set to Z-code, and Quixe if the format is Glulx. In fact, though, Parchment works with either format, and some users prefer using it. If we want to have Parchment even for a Glulx project, we can write:
…and that's just what will happen. In fact, Inform also supports the use of any other interpreter the author wants to try. If we have access to an exotic Javascript-based interpreter called, let's say, "Urbzig", then we can install it by putting it into the "Templates" subfolder of the ".materials" folder for the project:
"Vorple" is an innovative system by Juhana Leinonen for allowing web-based Inform stories to make use of web controls and other gadgets. Using Vorple, a story can in principle have an entirely different user interface, and can make much better use of CSS styling, interface to Javascript libraries, and so on.
Vorple has seen rapid development. In its early days it was included as part of the Inform app, but it has now evolved into a dynamic project which is better served by its own website than from here:
Web pages are very idiosyncratic things and Inform will almost certainly not produce exactly what we want. What it actually does is to take an existing "template" web page, and paste in the relevant information to make the final product. So by starting with a different template, we can end up with an entirely different-looking web page: like this one, for instance -

The template ordinarily used by Inform is called "Standard" and comes built in. (A second built-in template, "Classic", imitates the look used in 2005-08. The word "classic" here is to be understood in the sense of Classic Mac OS, the classic Doctor Who adventure "Time and the Rani", classic Mayan civilisation, and so forth – really pretty awful.)
Any other templates we must make ourselves, giving each one a different name, by convention a single word. In this section, we'll make a new one called "Platinum".
Suppose we write:
This is identical to the previous version except for the "Platinum": note the quotation marks. When it needs to find a template, Inform searches the following places in sequence:
What Inform looks for is a folder name matching that of the template – so in our case we need to provide a folder called "Platinum", and put it in either location (a) or (b).
The template folder is expected to contain some combination of the following files:
There are two HTML pages here, one for the main front page, the other for pages of displayed source text (if we release along with the source text – see later in the chapter). The CSS file defines styles of text – sizes, fonts, colours, and so on – and positions material on the page. The "(extras).txt" – which is optional, of course – allows additional HTML pages, images, movies and so on to be added.
If any of these is missing, Inform uses the one in "Standard" instead. In practice, this means the easiest way to create a new template is to supply just a new CSS file, which can change the colour, font, type size, and position of more or less everything in the site:
We probably want to start from the "Standard" version of "style.css" and edit in a few changes; the easiest way to get a clean copy of "Standard"'s CSS file to work on is to release the project with a "Standard" template, which causes this default "style.css" to appear in the "Release" subfolder of the project's .materials folder. (But it's wise to move the file out of "Release" before starting to edit it – files in "Release" are overwritten by Inform whenever a release is made.)
This is not the place to describe how CSS works. CSS is a more or less universal format today for describing how web pages should look – their style rather than their content. A dazzling variety of possibilities can be seen at the excellent:
but of course there are many, many other textbooks and websites which describe CSS.
The following describes how Inform uses the extras file and the two HTML pages in a template, and will only be needed if a new template has to make changes so radical that altering the CSS alone won't be enough.
The optional "(extras).txt" file – note brackets – is a text file which contains a list of named extras to throw in. For instance:
These named files need to be present in the template folder. Files with the extension ".html" go through the placeholder expansion process just like the index and source pages; all other files are copied verbatim.
HTML templates like "index.html" and "source.html" are fully valid HTML pages in their own right, though they have placeholder text where Inform will substitute the project's bibliographic data (see below). The "<head>" element should include a reference to "style.css", which of course will mean the CSS file given in the template (or the one from "Standard" if no CSS file is given) – for instance,
When it turns the template into the final web page, what Inform does is to replace certain capitalised words in square brackets with the appropriate text:
Everything else is left alone. In source pages, five further placeholders are available:
Both [SOURCE] and [SOURCENOTES] must exist on the page, and [SOURCENOTES] must appear after [SOURCE] does in the file. (Of course the CSS in "style.css" might move the copy around on screen, but that's another matter.)
Some long-time users of Inform will have projects which were originally made using the very different Inform 6 language. Story files produced with Inform 6 do not have any of the extra touches in this chapter: in particular, they have no cover art and no bibliographic data, which makes them rather plain and anonymous to newer Treaty of Babel-equipped programs like Zoom, Spatterlight or Windows Frotz.
To help with this, today's Inform can republish an Inform 6 project by combining an Inform 7 source text which contains only release instructions and bibliographic data with an already-compiled Inform 6 story file. We do this by writing a short source text which contains:
We then place the story file in the ".materials" folder. By default this will be called "Story.z8", but we can alternatively name it:
The Settings panel must be switched to the Z-machine for this to work, since only Z-machine story files are supported this way, not Glulx. And we can now use the Release button to obtain the goods.
An existing story file can take advantage of all of the extra features – cover art, titling, website, feelies and so forth – earlier in this chapter, but not those – walkthrough, source text, map – which are still to come.
The following is a typical example of a source text used solely to bind up an old Inform 6-compiled story file:
Since the earliest days of IF, players have distributed solutions to well-known stories, to help out other players at their wits' ends. The commonest format for these is a list of commands to type, sometimes with notes in the margin, and such a solution is called a "walkthrough", since it walks a player through the story.
Few authors publish solutions of their own works, but many supply their testers with solutions, especially towards the end of testing, or submit a solution as part of a competition entry. To help with this, Inform can generate such a walkthrough solution automatically:
Inform will then place a file called "solution.txt" inside the "Release" folder. The solution might look like so (although probably much longer):
Inform does not, of course, know how to solve IF all by itself, but derives the solution from the project's Skein. Since the Skein will have been used in testing the story, it will very likely contain a perfect solution – or several different ones, taking the story to a variety of possible endings. In the example above, there are two possible winning lines, which diverge right from the first move. (There can be further divergences: for instance, if branch (2) splits, it will split into branches called (2.1), (2.2), (2.3) and so on.)
But the Skein will also contain plenty of unwanted diversions, so Inform does not rewrite the entire Skein as a solution. Instead, it looks for knots in the Skein which have been annotated. Any knot whose annotation begins "***" (three asterisks) is considered to be a final, winning move. (It is probably a good idea to lock such a knot once it has been annotated thus, too.) We can mark any number of knots "***" since, after all, we can declare any number of lines of play as possible solutions. Inform then constructs the solution out of all lines of play in the Skein which lead to "***" endings, and ignores other threads.

Annotations other than "***" in the Skein are turned automatically into comments in the solution text. For instance, the knot for the INVENTORY command in the second branch above was annotated "Always a good idea", and this was transcribed into the solution. (If an ending knot is annotated with, say, "*** Happy ending!" then the "***" marks it as an ending, and "Happy ending!" is added as an annotation to that ending.)
By default, the solution text is not linked from our webpage, on the assumption that we may want to generate a walkthrough but not immediately advertise it to players. If we wish to change this, we may write instead
The terms public and private may also be applied to other elements we are having Inform generate to include on our webpage: see also the notes on private source text, below.
Most authors will not want to publish the source text alongside the work itself, because this gives away all of its secrets. Inform provides the option mainly for the sake of the examples published on its own website, where making the source available is the whole point. But anyone is welcome to use the option, of course:
If Inform is not also generating a website, this produces a plain text file called "source.txt" in the "Release" folder, and there is nothing more to be said.
However, if a website is also being released, the source is also converted to a suite of web pages which are linked to and from the home page. (Each heading with substantive content is placed on its own web page, with the opening page containing a contents list.)
Comments in the source are rendered in grey. As a special feature, any comment which begins with an asterisk is considered a footnote and is printed below the source text, with a link. Thus comments thus:
will be printed more like so:
Footnotes are automatically numbered from 1 on each source page.
By default, the source text is linked from our generated webpage, if we are releasing with a webpage. If we wish to change this, we may write instead
This will create a text file containing the source for our story, and place this file in our release folder, but not create a link so that the player can find it.
Finally, we can:
which releases a stand-alone XML file in 'iFiction' format for the bibliographic data on the story file; this is the same data embedded in the blorb file itself, but having an external copy makes it easier to see what Inform has done, and some external programs can read iFiction data like this.
As we have seen, "Release along with…" allows us to package up a work of IF with all manner of extra materials. But what are these to be? One popular option is to produce a map – sometimes partial, sometimes obfuscated – and supply that with the story: besides, there are some IF competitions where the rules require that the referee is supplied with a map even if the players are not, and failing that, it is sometimes nice to be able to print out a map of a work in progress.
The World map in the Index tab is heavily stylised and cartoonish, intended to be clicked on or moused over, and viewed in a browser: although it is, in fact, possible to print it, the results are not very good. Fortunately, the same underlying map mechanism can be used to output something more useful and very much more customisable, as we shall see.
The map-maker is one of the most complex parts of Inform, even though it actually contributes nothing to the final story file: the problem of how to draw up a "correct" map from the source text is by no means easy to solve. Inform tries, but it often gets things wrong. Its general practice is to place rooms on a square grid (actually a cubic lattice, as it works in three dimensions), but not all conceptual maps fit well onto this, and Inform often annoyingly puts a particular room in the "wrong" place. For instance, suppose Inform puts "Didcot" east of "Abingdon" and this makes the geometry look different to what we had in mind. We can correct with:
Note that this says nothing about exits from any room to any other room, and changes the final work of IF not at all: it simply helps Inform to draw the map index. (Instructions like this one are treated as being almost certainly true, but Inform does not quite always obey: it will never allow two rooms to be superimposed at the same grid position, no matter what we have asked in "Index map with…" instructions.) The same trick is useful if we have a situation like so:
"Beach Hut Interior" is a single room which does not connect to the rest of the map by any of the ten spatial directions, so Inform does not place it on the main map but instead moves it off out of the way in a map of its own. Given that it's just a single room, however, we might prefer to put into a convenient otherwise empty grid position like so:
Finally, note that this trick also ensures that the two locations are mapped on the same level vertically, and can be useful in cases where room A is both north of and above room B: Inform will want A to be higher up than B, but we can insist otherwise.
The "Index map with…" instruction is a much more varied thing than hinted at in the previous section, and its general form is
where the instructions can be of four different forms, as follows:
We have already seen the first of these instructions. The second is short and has a fixed wording:
so can be invoked by typing "Index map with EPS file.", for instance. EPS stands for Encapsulated PostScript, which is a standard file format for line art. EPS files can be edited with sophisticated graphics programs such as Adobe Illustrator, and can be used as illustrations in many word-processors and page layout programs. They can also be converted to PDF by Mac OS X Preview, or used in Linux or Windows with the open-source Evince viewer. We need a line-art format because the map produced will never be exactly what we want: we are probably going to end up hacking it to change the fonts, add some drawings, tidy up the spacing and so on. A really large map will end up using quite a large "canvas", in EPS terms; it may be necessary to shrink it down in order to get it onto an A4 page, or to adjust whatever editing software is used to "custom paper size".
When the map-maker has been given the "EPS file" instruction, it writes an attempt to draw the current project's map in EPS format as a file in the project's ".materials" folder, with the filename "Inform Map.eps".
Note that Inform will over-write any existing file of this name: but that is intentional, because one usually ends up tweaking and rebuilding the project over and over to get the map just so, and it would be tiresome for Inform to produce endless copies "Inform Map 19.eps", etc.
(The reason the EPS file is not placed in the Release subfolder is that it is not going to releasable to the public as it stands: for one thing it will be too raw, and for another, EPS is not a format everyone can read. It is provided as raw materials.)
The map-maker has altogether 35 named settings, and tweaking these can affect the result in ways which vary from the subtle to the grotesque. An important point is that the map-maker deals separately with the three levels in its working: the big picture of the whole map; each of the vertical slices which contain sub-maps; and finally all of the individual rooms. For instance, we might have 67 rooms, arranged on 3 vertical levels, all shown on one big map: Inform will try to show these stacked above each other, with the highest level at the top of the map, then the middle level, then the bottom level.
Moreover, not only does the whole map have its 35 settings, but each level has its own independent collection of those 35 settings, and so does each individual room. So the actual number of variables in our example is 1+3+67 = 71 times 35, which is a lot. The convention is that setting the value of S (some setting, let's say) for something affects not only that thing, but also everything inside it, unless they have their own individual settings for S.
For example: one of the settings is called "room-size", and is the size of the little square boxes representing a room, measured in points. (One point is 1/72 of an inch, so 72 points equals 1 inch: it's a traditional printer's measure.) Suppose we write:
The first instruction sets the value of "room-size" for the whole map (note the lack of an "of…"); the second for level 2 of the map, and the last for a single room only. The result is that the Hall of Kings is drawn as 52x52 point box, all rooms on level 2 are 28x28 (except the Hall of Kings, if it's on level 2), and all others are 36x36, half an inch square.
The setting instruction also allows three other useful forms. A setting "of the first room" applies to the room in which the story begins: we might for instance write
which gives this special room a bolder edge to it, since the default value is 1.
We can also apply settings not just to single rooms but to all rooms of a given kind:
Lastly, we can apply settings to all rooms in a given region:
(Note that rooms and regions don't have their own individual sets of the 35 settings: what happens is just that instructions like the last one change more than one room at once.)
Note that all map-maker settings have single word names, though many are hyphenated, and that "colour" is always given the English and Canadian spelling, not the American form "color".
| font | font (named in double-quotes) |
| minimum-map-width | integer (measured in points: 72 = 1 inch) |
| title | text (in double-quotes) |
| title-size | integer (measured in points) |
| title-font | font (named in double-quotes) |
| title-colour | colour (named in double-quotes) |
| map-outline | on/off |
| border-size | integer (measured in points) |
| vertical-spacing | integer (measured in points) |
| monochrome | on/off |
| annotation-size | integer (measured in points) |
| annotation-length | integer (length to abbreviate down to) |
| annotation-font | font (named in double-quotes) |
| subtitle | text (in double-quotes) |
| subtitle-size | integer (measured in points) |
| subtitle-font | font (named in double-quotes) |
| subtitle-colour | colour (named in double-quotes) |
| grid-size | integer (measured in points) |
| route-stiffness | integer (Bezier spline curve scale factor) |
| route-thickness | integer (measured in points) |
| route-colour | colour (named in double-quotes) |
| room-offset | offset (in percentages of grid-size) |
| room-size | integer (measured in points) |
| room-colour | colour (named in double-quotes) |
| room-name | text (in double-quotes) |
| room-name-size | integer (measured in points) |
| room-name-font | font (named in double-quotes) |
| room-name-colour | colour (named in double-quotes) |
| room-name-length | integer (length to abbreviate down to) |
| room-name-offset | offset (in percentages of grid-size) |
| room-outline | on/off |
| room-outline-colour | colour (named in double-quotes) |
| room-outline-thickness | integer (measured in points) |
| room-shape | shape (named in double-quotes) |
Integer values are typed in the usual way: 3, -72, etc.
Text is in double-quotes: "Map of Lower Delta", etc.
Font names are in double-quotes: "Helvetica", etc. Note that Inform makes no effort to look for such fonts: if we give the name of a font we haven't got, the result will probably be that the map's EPS file will be displayed in various applications with Courier (which looks like bad typewriting) substituted. All fonts are by default equal to the global "font" setting (by default equal to "Helvetica"), so changing "font" for the whole map affects everything not explicitly specified as having a different font.
Shape names are in double-quotes with lower case. At present, the only legal shapes are "circle", "square" and "rectangle".
On/off values are written just thus: on, off. No quotation marks.
Offset values are actually pairs, and are written as two numbers (possibly negative numbers) joined by an ampersand, as in the example: "Index map with room-offset of Botley set to 10&-30." Note lack of spaces around the ampersand. This means that Botley's room is displaced from its correct grid position on the EPS map by 10% of the grid size eastwards, and 30% southwards. (The grid size is the distance between one grid position and the next: displacing Botley by -200&0 would move it two whole grid positions westwards.)
The route-stiffness setting is used when drawing routes between two rooms. These are drawn as Bezier curves, a standard way to make a smooth curve not only travel from A to B but also from pointing in a given direction at A to ending up pointing in a given direction at B. Thus a Bezier curve may turn a route round so that it leaves A pointing west, but curves around to enter B from the south. (Most routes involve leaving in one direction and arriving in the opposite direction, of course, and in those cases a Bezier curve is just a straight line.)
The stiffness factor for a given room measures how much the curves are allowed to warp around in order to force them to arrive at that room from exactly the right compass bearing. The default is 100. Raising to, say, 250 can force curved paths into freakish zig-zags: whereas lowering to 1, the minimum, may make the route arrive at completely the wrong bearing. (Formally speaking: at each end of the route, a "control point" for the Bezier curve is made by taking the centre point of the room, then adding the relevant compass bearing's vector, scaled up by the route-stiffness as a percentage of the grid size.)
Colour values are named and in double-quotes. These names are the same as those for the traditional set of web-page-safe colour chips, as follows:
The main title of the map is the value of "title" for the whole map, so for instance we might write:
The subtitle settings apply to the subtitles used for each of the levels, so for instance
Names of individual rooms can be controlled with:
(By default, the name of a room is its name in the main IF project, of course.) The smallest writing on the map is normally that used to label unorthodox or unclear exits (in particular, those going from one layer to another): this is what the "annotation" size, font and colour are used for.
For most ways to set up the map, it's a practical necessity to abbreviate names of rooms, or they will spill out all over each other. Inform does this using the "room-name-length" setting. (The "annotation-name-length" is analogous.) For instance, if this setting is 5, then Inform will reduce the text of a name to at most 5 characters. It does this by successively throwing out spaces, lower case vowels, then other lower case letters, punctuation marks and finally upper case letters, always starting at the back of the name and working inwards: the process stops as soon as the name is short enough. For instance, "Reading" is abbreviated to "Redng", "Shangri-La" to "Shn-La" and "Cloud-Cuckoo-Land" to "C-C-L". The result can be a little comical, but is surprisingly unambiguous in practice. Abbreviation can effectively be abolished by raising the "room-name-length" to 128 (the highest permitted level), and note that the setting can be changed for individual rooms, so it is possible to have some room names abbreviated and others not, or in different degrees.
Lastly, we can add our own arbitrary text to the map: perhaps to annotate points, perhaps just to add more heading matter (such as the author's name, or the date). Each individual line added – and only single lines can be added, not typeset paragraphs – is called a "rubric". (There can be up to 100 of these.) We can create a rubric like so:
This gives rather more detailed information than is needed: "size 16" could have been omitted, giving us 12-point type by default, and similarly there is no need to specify a font unless it differs from the main "font" setting for the whole map; and the colour will be black if unspecified. The "at" position does need to be given, though. Note that it is relative to a given room on the map, and that the position specified is that of the centre-point of the text. (If we had written just "at 100&100", say, that would specify a position relative to the bottom left hand corner of the map.) So, for instance:
would add a little 8-point-type safety tip for naive map-followers.
Inevitably, the settings in the map-maker will fail to get exactly the effect desired (though they will offer an excellent opportunity to waste entire days). But that is the whole point of producing output in EPS format: Inform aims not to produce final print-ready professional art, but to produce the raw material for making that final work of art. And if all that's required is a sketch-map, then Inform's output should be good enough quickly and without too much fuss.
So the new work of IF is written, and tested, and has all its bibliographic data and a fancy cover illustration lined up. What next?
Releasing and gaining attention for independent games – commercial or otherwise – is a big, complex, and constantly changing field, and other online sources will be able to provide more up-to-date information than we can offer here. However, there are some resources, events, and community spaces specifically for authors of interactive fiction and text adventures in particular.
First, though, a word about terminology.
For many years, the phrase "interactive fiction" referred primarily to parser-based games like the ones Inform produces by default. For those games, there has always been an avid hobbyist community, but few sales, and most parser IF writers have not felt that it would be more trouble than it was worth to charge for their games, because the income would be slight relative to the effort of setting up a storefront.
In recent years, other forms of interactive fiction – those that do not rely on typed input from the player – have experienced a commercial revival. There are a number of commercial game studios that write text-rich, choice-driven stories, especially for a mobile market.
Simultaneously, the communities of interactive fiction readers and players have grown and diversified. Once "the IF community" referred to a specific group of people; now, there are many communities of people who play text-based games, in various formats, with various amounts of overlap.
Although it is not a typical tool for choice-based mobile games, Inform has been used to produce commercial works, both parser-based and not. Users are very welcome to sell works created by Inform with no royalty or requirement for rights clearance. It's also widely used in education, and as a prototyping tool for other kinds of stories, such as interactive narratives that will ultimately take another (not text-based) form.
Authors coming from a literary background may think in terms of editing; people coming from software development and the game industry may think about playtesting and quality assurance.
Whatever the background, it's good practice to have your work checked by other people before you release it. Other players can identify issues from typos to missing hints to thematic incongruities.
Play-testers can often be recruited by placing an ad on intfiction.org.
One option for sharing your work with the world is to set up a web page and a copy of the story file on a private web host. That host should ideally be as stable as possible, so that the URL is likely to remain fixed for what might be a long period. Freeware stories have a long period of viability relative to commercial games, which means that players may still be hearing about and checking out a story years after its initial release. A stable address helps everyone with links, and makes it easier for search engines to direct people.
Of course creating a web page involves a little design work, but tools are widely available which make this quite easy nowadays. And as we've seen, Inform can automatically generate web pages and whole small mini-sites to put all the information about a story file into a tidy format, even including the ability to play online.
A second approach – instead of or alongside giving the game its own website – is to put it on a distribution platform designed for sharing games.
One of the most accessible is itch.io. While it's a lot of work to put a game on a mobile app store or on Steam, setting up a storefront at the itch.io site takes only a few minutes. Doing so enables an author to list a game for download, set a price for their work or just to accept donations of the player's choosing.
A game on itch.io will still need promotion and other attention if the author hopes to make any significant amount of money, but the barriers to listing something for sale are much lower than they once were. And itch.io can be a viable way to share a game that isn't intended to charge money at all.
At the time of this writing, the itch.io platform lists 15,988 games tagged "interactive fiction."
Games and interactive works in general tend to become obsolete or unplayable fairly quickly. Many games written for iOS in the mid-2010s, for instance, are already impossible to access.
Because of the portable underlying format, however, games written in Inform are unusually stable and maintainable. Inform projects written in the early 90s can still be played – indeed, can be played on platforms that did not exist when the games were written.
If you're interested in the longevity of your project, you may want to submit the final version to the IF Archive.
The Archive is a mirrored, stable collection of thousands of interactive fiction games and programming languages, manuals, fanzines, maps, walkthroughs, and other materials. As such, it's likely to stay around even if a personal website goes off-line; it's also the primary resource for people doing scholarship on interactive fiction (and there are a growing number of these).
The Archive is very much a library, for long-term archiving, rather than a book-store. The catalogue is sober and textual, and there are no visual shop-windows, or posters advertising new titles hot off the press. Newcomers sometimes need practice finding their way around. And the Archive hosts story files (and associated manuals, as appropriate) but not advertising for them – it does not provide web-hosting for authors to set up mini-sites.
Uploading a work to the IF Archive is not too difficult, and can be done in two ways. One way is to use the archive's web form at:
The other is to create a new page at the Interactive Fiction Database, at:
It's then possible to upload the story file to the IF Archive from IFDB. This is easiest all round, since it allows both IFDB and IF Archive to be updated at once.
In either approach, an author chooses and uploads a file, and accompanies it with a name and email address (so that the archive maintainers can verify the legitimacy of the work). The "About this file" field is for a line or two explaining what the story is -- its full title and any critical information -- and is used in generating the archive index. This is normally much shorter than the "blurb" described earlier. There's also a field to suggest where in the archive the story should be stored, but this is optional and intended chiefly for people expert in how the archive is filed. The archive maintainers will file a new story file in the obvious directory for its format. For Inform works, that means other Z-Machine – "z-code" – or Glulx story files. The maintainers sometimes place the same story file in multiple places in the Archive, using links.
As with all large libraries, it takes the Archive a little while for new acquisitions to be processed. When this happens, one of the volunteer maintainers will email with the official URL from which anyone can now download the story file.
Committing a story to the Archive is meant to be permanent. While the maintainers will happily replace older versions of stories with new improved releases, they are less eager to remove stories entirely. If that doesn't seem appealing, or if we do not want our story to be treated as freeware with essentially unlimited distribution, the Archive may not be a good choice. But it is deeply valued by the IF community, and has saved many works which could otherwise easily have been lost forever. Many contributions important in the history of IF were made by people who are now not easy to trace, and whose websites are long gone. But their work lives on.
Once the story file has a home online, and a URL (that is, a web address) at which it can be found, it needs to be registered with IFDB:
the Interactive Fiction Database. Just as the IF Archive is a repository for stories themselves, IFDB is a database containing information about them – titles, authors, locations, solutions, reviews, recommendation lists and more.
The name IFDB echoes the Internet Movie Database (IMDB), but in some ways it is also like the iTunes Music Store. For one thing, it's a shop-window for what's new, with cover art to catch the eye. For another, IFDB serves as a portal for players to try games directly in their browser. Promoting IF is all about pulling in impulse players -- people who are passingly interested, but might not try the story if there is any significant work involved in setting it up. This is what IFDB is all about.
IFDB is community-editable, like Wikipedia, though editors are required to create an account and log in first -- this is free, of course. A standard form is provided for creating a new record (accessible by selecting the option to add a story listing). More or less the same information that appears on Inform's library card in the Contents index needs to be copied over: there's space for the author name, story title, genre, and so on. IFDB will also ask for an IFID, a code identifying the story uniquely. Inform generates one of these automatically for each project, and it, too, is on the Library Card. It can always be found by typing VERSION into the compiled story and looking at the line that says
Identification number: //[some letters and numbers]//
The part between the // marks is the IFID. If there's cover art, that can also be uploaded, and good cover art makes a big difference to shop-window-appeal.
The download link should give the most stable URL available. If you have not yet uploaded your story to the IF Archive, you may do so by selecting the "Upload it to the IF Archive" link instead of pressing the "Add a Link" button. The benefits of submitting your story to the IF Archive in this manner are two-fold. One, IFDB will fill in much of the information required by the IF Archive for you. Two, the link to your story will not appear until the IF Archive maintainers move it to its permanent home in the archive, at which point the download link will be automatically updated and presented on the story page.
If you choose to upload your story file to the IF Archive independent of IFDB, then once the story file is safely up at its permanent home on the IF Archive, that is an ideal address to quote here. Otherwise, the URL of the work's own website is best. (Note that the IFDB entry can always be edited later, if the URL moves.)
Commercial works which aren't available as free downloads can be registered on IFDB just the same, and this is almost certainly a good idea.
Some awards for interactive fiction, such as the annual XYZZY Awards, require a game to have an IFDB entry as an eligibility requirement.
One very common way to get players for IF is to enter the story into an IF competition. The annual IF Competition, often just called IFComp, is the most prestigious and has the widest field, but the Spring Thing, ParserComp, EctoComp, and other events also catch people's attention. Entering a competition is a path of least effort for authors promoting their new work, because the competition organizer usually takes care of hosting and archiving submitted stories, promoting the competition as a whole, collecting votes, and encouraging players to post reviews. Different contests have different arrangements. The ifwiki usually posts a list of current and upcoming competitions, as well as lists of results for those recently past, on the front page:
Some competitions also have their own websites, at least at the relevant times of year.
All the same, there are many IF works that aren't cut out for competition release. Competitions tend to be best for short or medium-short works, because judges don't necessarily have time to play a lot of long stories at once, and sometimes this is a condition of entry.
It's also good for publicity to win one of the annual XYZZY Awards. All interactive fiction stories released in a given year are eligible, as long as they are listed on IFDB.
Meanwhile, itch.io hosts many jams every year. A small handful of these are specifically intended for interactive fiction or parser-based adventures, but there are many other jams that allow entrants to put up any game with an appropriate theme, regardless of its format.
lists the calendar of everything currently upcoming.
Finally, if your project is heavily focused on procedural generation – creating or remixing elements on each playthrough – then it may have a natural home at procjam:
Procjam is a yearly event to "make something that makes something", and welcomes all kinds of generative projects, whether they are games or not.
There are a number of different local groups that get together to play or discuss interactive fiction, including a number that hold remote meetings. Announcements of some of these can be found at
Joining these groups may provide a context to discuss work in progress, and many are willing to do a group playthrough of games written by group members.
There are also a range of conferences that accept talks or presentations about interactive fiction, both academic conferences and conferences adjacent to the game industry. While it is not a complete listing, Emily Short's blog attempts to link upcoming events:
It's natural to want to make a huge splash with a story, but in the IF community, instant widespread adulation for any work is pretty uncommon.
For one thing, players tend to play when they get around to it… which may be weeks, months, or even years after the initial release. Reviews trickle rather than flooding in. Appreciation builds slowly. And sometimes works that placed unspectacularly in a competition, or seemed to be overlooked in the annual XYZZY Awards, gradually come to be regarded as classics because of some pioneering technique.
So it's wise (if difficult) not to judge a story's success entirely by its immediate feedback. Even after its debut, a story can often use a little care and attention if it's to reach all its potential fans -- whether that means building further releases, posting hint files or walkthroughs, developing new websites, or approaching outside reviewers.
The range of simulation offered by Inform's model world is intentionally limited to a core of basic essentials. We could argue at the margins, and the choice of what's in and what's out is partly traditional, but most people find the model reasonable as far as it goes.
Between 1993 and 2006, quite a range of "library extensions" for Inform's predecessor language (Inform 6) was written. Most of these extensions aimed to fill out the model by simulating other aspects of life, too: money, clothing, pourable liquids. None of these extensions was official and all of them were: it was a free-for-all, and in several cases different authors wrote rival extensions to model the same basic ideas. The development of Inform 7 was strongly influenced by this history and by the recognition that the base of rules and grammar inside a typical modern story are seldom written by a single author. They combine the standard Inform material with extensions by several third parties, together with anything specific to the story in question.
Inform 7 has a more organised idea of extensions, as we shall see. But anyone is free to write an extension on any terms or for any reason. Writers may wish to use the techniques in this chapter to develop private extensions of their own, used in several projects, or to share them with associates but not more widely.
But most writers of extensions do so to contribute to the Inform community, and for the satisfaction of solving a problem. Inform does not recognise anyone's approach to a particular need as "the official solution" – for instance, although the standard Inform distribution includes a copy of Locksmith by Emily Short, that is not the "official" way to make automatically unlocking doors, and anyone is welcome to try a better one.
However, the Inform project does recognise some extensions as "public". Public extensions are the ones archived on the Inform website for the free use of all Inform writers. Those who wish to contribute an extension as a public one are obliged to follow a number of guidelines, which are mostly stylistic points intended to make the range of extensions easier to work with. Extension writers are asked to join in the spirit of these rules and help make the whole cooperative enterprise work harmoniously. Extensions which do play by these rules are also accepted into the Public Library, which makes them easy for all Inform users everywhere to find and obtain them.
Writers who wish to make their extensions public on the Inform website should also be clear that by doing so, they are donating their work to the community on the basis of the broadest form of Creative Commons license: that is, they retain copyright and the right to be identified as the author (and as we shall see they are automatically credited in any work of IF which uses their extension), but are giving unlimited permission to use, circulate and republish their extensions in any form, even as part of commercial works (should that arise). To publish a public extension is a public-spirited act, done for only the reward of a modest acknowledgement.
If the author of an extension has not made it public, or indicated in some other way that it is free to be used without the need for permission, then it would be both polite and prudent to check with the author before publishing something which incorporates his work.
When any source text is run through Inform, a secret first line is inserted, which reads:
The "Standard Rules" file contains the definitions of the basic kinds, phrases, actions and grammar described in this documentation: for instance, it includes lines like
…without which Inform would be lost. Although including the Standard Rules is compulsory, it is treated internally as if it were any other "extension".
What happens when an "Include" sentence is reached is that the sentence is replaced with the whole text of the file in question, often many paragraphs long.
If the file has already been included, then the sentence is simply ignored. This is so that we can have two extensions, each of which needs the other: if A says to include B, and B says to include A, the result is that including one automatically includes the other, so we always get both which ever we ask for – not that there is a hideous infinite regress.
To recap: Inform builds projects from both the source text typed by the author and from Extensions; one of these, the Standard Rules, is always included; others are added as authors please. About 20 are "built-in" to Inform, meaning that they are stored inside the application and always available. Others must be "installed", and each Inform user will have a folder somewhere on his computer which contains these. Users typically obtain these from the Public Library feature in the Inform application, but can also download them directly from the extension writer's website and then use an Install Extension menu option in the application. Either way, the application then squirrels the file away, and it becomes available to any projects that that user may be working on.
It is also possible to have extensions available to just one project. These must be stored in the Extensions subfolder of the project's ".materials" folder, but otherwise are arranged the same as installed extensions – there's an outer folder for each author's name, and extensions are named with a ".i7x" extension within. For example:
When Inform needs to find an extension, it looks here first, then in the installed area, then in its built-in area. That means that we can make our own revised or hacked version of an extension, put it in the ".materials" area, and then have it take precedence over the installed or built-in one. We could even have our own private version of the Standard Rules here.
(This has a number of possible uses – for example, to provide a convenient test-bed when working on an experimental version of an extension.)
Extensions are identified by author and by name, so that a given author can produce his or her own range of extensions, and need only ensure that these are named differently from each other. If John Smith and Mary Brown each want to write an extension called "Following People", there is no conflict.
The name of an extension, and of an author, should be written in Sentence Capitalisation: that is, upper case for the first letter in each word. (Inform uses this to minimise problems on machines where filenames are read with case sensitivity.) It is permitted for author names to include upper-case letters within words, as with the "G" in "Jesse McGrew". In general it is best to avoid accented or unusual letters in titles and author names, but the standard ISO Latin-1 characters should be allowed – for instance,
The author name must not start with "The", nor contain the words "by", "and" or "version", or contain punctuation, as in "John X. Doe"; the title similarly, except that "and" is permitted. Name and author's name must each be no more than 50 characters long, including any spaces between words.
Authors are asked to use real names rather than cryptic handles like "ifguy", and to use genteel, plausible pseudonyms like "Emily Short" rather than, say, "Drooling Zombie" or "Team Inform". Authors are also asked to use the same author's name for all their own extensions, and (it should go without saying) not to masquerade as anybody else.
Sometimes authorship is complicated. What if Mary Brown finds some Inform 6 code written by John Smith in the mid-90s, and puts an I7 gloss on it to make an I7 extension, but then Pierre Dupont translates it into French: who's the author of the result? The rule is that the person making the current, latest version is the author listed in the titling line, so we end up with
But Mary and John deserve their credits too: see the next section for how to give them.
Extensions are plain text files, and can be created with any text editor. (It is sometimes said that "there is no such thing as plain text", there being so many ways to represent exotic characters: so to be precise, an extension is a text file with the Unicode UTF-8 encoding, either with or without a BOM marker, using any of the possible forms of line-ending (Unix, Windows, Macintosh, or Unicode line divider). This is a detail which will only matter if the extension contains accented letters or other exotica.)
Extensions look very much like passages of Inform source, because except for a special introductory and concluding sentence, and one convention, that is all they are:
Not a useful or interesting extension, but those few words add a whole new action and everything needed to make it work. It is Inform's ability to mix up rooms, things, kinds, grammar, phrases and rules, in more or less any order, which makes it possible for extensions to work.
The introductory sentence must be placed as the only content of line 1 of the file, which must not contain comments, and has to be written in exactly the correct form. Inform checks this very carefully when performing its census of installed extensions, on each translation of the text. (In case the extension's title is a plural, we are allowed to write "begin" and "end" instead of "begins" and "ends". For instance, the last line of the standard rules is "The Standard Rules end here.")
The "one convention" mentioned above is that if a double-quoted text is placed immediately after the beginning sentence (and with no intervening comments), then it is taken to be a short description of the extension's content called the "rubric". Hence the line:
Providing a rubric is helpful, because it enables Inform to give a meaningful listing even for an as-yet unused and unindexed extension, and because it helps the Inform website to produce better directories. Note the word "short": such text is likely to be truncated if it exceeds 500 characters.
A second double-quoted text can also, optionally, be added in yet a third special starting paragraph. This is to provide additional credits to people who have contributed to this or earlier versions. For instance:
Note the typical style here: it's a phrase rather than a sentence, and neither starts with an upper-case letter nor ends with a full stop. (The additional credit is then used in documentation and also in the VERSION text of any Inform story file using the extension.)
As we have seen, extensions are referred to by name and author, but they can also (optionally) be referred to by version. For instance:
Version numbers should consist of one to three whole numbers divided by dots, with no negative numbers allowed. Thus "5", "3.3" and "2.1.71652" are all valid as version numbers, but "-4" and "3.1.2.5" are not. Any numbers not specified are taken to be 0: thus "3.3" means the same as "3.3.0", and "5" means the same as "5.0.0".
In versions of Inform before 2022, versions of extensions were also allowed to be written in the form "N/YYMMDD", as in this example:
The material after the slash '/' was expected to be a date, so that 040426 would mean 26 April 2004. In order to preserve compatibility with old extensions, Inform continues to allow this notation, but treats it as equivalent to writing "N.0.YYMMDD", though with any leading 0s trimmed. So the above sentence is equivalent to writing:
Extensions are usually intended to be shared and passed around between Inform users, and good use of version numbering can be a huge help to those users; and it's helpful if we can agree as a community on what good version-numbering is. Because of that, the Inform project tries to use a widely-recognised Internet standard called "semantic version numbering".
For full details see semver.org, but for Inform purposes the following fairly simple rules should be enough. "Semantic" just means that version number changes should communicate something meaningful. So, whenever an extension author puts out a new version of an extension, the extension number should change in a way that signals how drastic the change will be.
In this system, the three possible numbers X.Y.Z are called the "major", "minor" and "patch" numbers. Every time an extension is changed and re-released, even just informally among friends but certainly if posted somewhere on the Internet, X, Y or Z should change. The rules are:
(X) If the extension has changed so much that Inform projects using it will need to be changed in order to keep on working – for example, if a "To…" phrase has been taken out, or the name of a kind changed – then X should be increased. Y and Z then usually go back to 0. This is a "major version".
(Y) If the extension provides new features but doesn't do anything to change the way its existing features are used, then X can stay the same but Y should increase, and Z then usually rolls around to 0. This is a "minor version".
(Z) If the extension has changed only to fix bugs, or make its existing features work more efficiently, or provide better documentation or examples, then X and Y can stay the same but Z should increase. This is a "patch version".
So, for example, a user who currently has version 3.2.7 can update to 3.2.8 without really investigating. That same user can update to 3.3, 3.4, … without any trouble, choosing either to use or ignore whatever new features they are presenting. But the user knows that moving up to version 4 might well require some work – a project using version 3.Y.Z will likely need writing to adopt version 4.
Now let's turn to "Include" sentences. A request like:
will be happy with any version of the extension at all, whether numbered or not; but
will only accept the extension if its version number is "compatible" with 2.4, which means, if it is 2.4 or later, but still belongs to the same major version, "2". So if we write this inclusion sentence, but the version we have installed is version 3.1, Inform will give a problem message. The fix may well be as simple as changing the inclusion sentence to match – but it may not, because a change in major version number is a signal that things have changed a lot inside the extension (see above).
During play of any story compiled by Inform 7, typing VERSION lists various serial numbers of the pieces of software used to make it. The list concludes with names, authors and version numbers of any extensions used. So every author whose work contributes to a story automatically gets a modest credit within it. The same list can be printed, at the discretion of the designer, using the textual substitution:
This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Extensions whose authors have chosen the "use authorial modesty" option are missed out.
If we want our extension to go uncredited – perhaps if it is a low-level enabling sort of thing, for instance – we can place the following sentence inside the definition of the extension:
The same sentence placed in the body of a source text causes all extensions by the same author as the main source text to go uncredited. In other words, if Isaac Miggins writes a source text and includes, say, Unlikely Events by Isaac Miggins, then this extension will go uncredited in the VERSION command.
A complete list, undiluted by modesty, can always be obtained using:
This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Every extension is included, even those whose authors have opted for "use authorial modesty".
Inform compiles to several different story file formats, and in each case uses only a small part of their abilities – especially when it comes to fancy tricks with the keyboard or screen. So people may well want to write extensions which provide access to some of these tricks (like "Basic Screen Effects", included in the standard Inform distribution, but more so). Unfortunately, these tricks are very likely to fail to compile – or fail to work – on some of the possible story file formats, so the resulting extension would probably go wrong (and mysteriously wrong) for users who have chosen a different format.
Inform therefore provides a way for extensions to declare the formats they are compatible with. All that is required is to add a proviso in brackets after the title is declared:
Other examples might be "(for Glulx only)", or "(for Z-machine only)". If no such proviso is given, the extension is assumed to be compatible with every story file format.
Extensions are also able to include material which is only used on some story file formats and not others – in principle, this might allow the same facilities to be provided to the author whatever story file format is used, but to achieve these effects differently depending on the current Settings. The convention here is exactly like "not for release": if a heading or subheading in the source text contains a bracketed proviso, then the material under that heading (and under its dependent subheadings) will be ignored if the current story file format does not match. For example:
would ensure that "reveal the explosion" works nicely whichever story file format is used.
Extensions can themselves contain "Include…" sentences asking for other extensions to be included. An extension might, for example, start like this:
A project which asks to include "Basic Help Menu" will then also include "Menus", even though the author might never even realise that. Indeed, the author could also have asked to include "Menus", not realising that "Basic Help Menu" was going to ask for the same thing.
So the same extension is often requested multiple times. This is fine if the version numbers in the requests are compatible, but they might not be. For instance, suppose the main source text asks to include version 2 of extension X, and also to include extension Y. Suppose further that Y contains a request to include version 4 of X. We now have two different requests for X, and they contradict each other – the major version of X cannot be both 2 and 4 at the same time. So Inform will produce a problem message in this case.
But in cases where it is possible for everyone to be satisfied, Inform will try to find a solution. If one extension asks for version 2.3 of X, and another asks just for X, and a third asks for version 2.7.2 of X, then Inform will work out that any version number in the range 2.7.2 up to (but not including) 3 will be fine. If it can in fact find such an extension, it will then use it. So if the user has version 2.8.17 installed, everything is fine.
If an extension does include other extensions, it is good style to place the "Include…" sentence(s) as early as possible after the introductory sentence, just so that human readers looking at the text of the extension can see these dependencies easily.
When one extension is being used, it's probably only one among several. A really general-purpose extension might want to behave differently depending on which other extensions are also present. This can be achieved using headings which are "for use with" (or "without") other extensions. For instance:
specifies that everything under this heading (and its subheadings, if any) will be ignored unless the extension Locksmith by Emily Short is included. Conversely,
will be ignored unless it isn't included. This allows an extension to give two variations on the same material – one if Locksmith is present, the other if not.
Headings can also replace portions of extensions which have been included. For instance:
places the source text under the new heading in the place of the old (which is thrown away). If there should be two or more headings of the same name in the given extension, the first is the one replaced; if two or more headings attempt to replace the same heading in the given extension, the final attempt in source text order is the one which succeeds; and finally, heading dependencies like the above are scanned in a top-down way. Thus, if we have:
and we don't include Locksmith, then the replacement of Section 4 of Marbles is not made, because Section 1 – Hacked marbles is subordinate to the Chapter 2a heading which we've told Inform to ignore.
If the name of the heading to replace contains the word "in", it's a good idea to use quotation marks for clarity:
As soon as a project has successfully been translated, its Index is brought up to date: pages of the index record all the kinds and what they are for, all the phrases which can be used, and so on. Any kind or phrase created in an extension is automatically included. The extension's presence in the project is itself recorded – the Contents index for any project contains a brief list of all extensions used in that project, along with their authors and version numbers.
The Kinds index aims to give the reader a brief note of what each kind is intended for. We can provide for this by writing a sentence like so:
There is no need to specify the properties which apply: that is all done automatically. "Specification" is a sort of pseudo-property used just for this: we can also give specifications to kinds of value and to actions, and these are similarly used in the Index pages.
Every extension has the right to its own set of headings and subheadings, independently of those used by the main source for the work or by any other extension which may be included. (So if the extension is divided into four sections and finishes on Section D, say, that doesn't mean that Section D will continue outside the extension as the main source of the story runs on.)
Extensions should, of course, be written so that they never produce Problem messages, so at first sight it appears that these headings will never be outwardly visible. In fact, though, Problems do occasionally turn up in extensions, usually when the user has made a mistake, or when two inconsistent extensions are used in the same project. But more importantly, the headings in an extension are used when indexing phrases (and also actions) to group similar phrases together. For instance, the Standard Rules contain the heading:
The half-dozen phrases defined in this section of the Standard Rules are then indexed under the subheading "Searching and sorting tables": Inform looks for a hyphen in the heading and then uses any text which follows the hyphen. (If there is no hyphen, the entire heading text is used.)
If an extension contains no headings, its phrases (or actions) are indexed simply as "Miscellaneous".
Finally, any phrase or variable defined immediately under a heading whose name ends in the word "unindexed" will be omitted from the Phrasebook or Contents index respectively. (That won't apply to definitions under subheadings of the heading.) This is intended so that technical apparatus used only inside the extensions can be concealed from the outside user's immediate view. Inform as it is presently constituted does not allow extensions to make fully private definitions, but this feature at least allows them to make unadvertised ones.
A basic mechanism for documenting extensions is built into Inform. For many extensions, this will probably do instead of a manual; for more complex ones, it should still prove a useful supplement to one.
As described in Chapter 2 above, whenever an extension is installed, its documentation is made available to the user. Such text should be written concisely, while giving examples wherever appropriate. Stylistically, it should ideally follow the model of the main Inform documentation: just as an extension expands the standard rules, so its documentation expands this manual. "We need…" is preferred to "You need…", and so on: we're all in this together.
In order to be recognised as documentation, this text should appear at the foot of the extension file, after the compulsory end sentence. The first paragraph must have exactly the following form, with a skipped line before and after:
For instance, the "Ducking Action" example might end:
We obtain indented code examples by beginning a line with a tab. A double indentation can be got with two tabs in a row, and so forth. (Beware: some text editors, or emailers, flatten tabs into a row of four or perhaps eight spaces each. Inform will not recognise such a line of spaces as a tab.)
Note that text in square brackets should be avoided in the documentation, because that's taken as being comment matter on the extension, and omitted.
Tables should be similarly indented, and should begin with the word "Table …": the top line is taken to be the name of the table, and subsequent lines are tab-divided columns. Inform will automatically group this into a table, like so:
| stellar object | example |
| galaxy | "Andromeda Galaxy M31" |
| star | "Sirius" |
| planet | "Neptune" |
| moon | "Enceladus" |
| dwarf planet | "Ceres" |
| plutino | "38628 Huya" |
| cubewano | "Easterbunny" |
(Footnote: Since the first appearance of this book, Easterbunny has been renamed Makemake, the creator god in the mythology of the people of Easter Island.)
Extensions with very large amounts of documentation can, if the author chooses, divide the material up using headings and/or subheadings. These must be written as paragraphs exactly like so:
Inform will then typeset them to stand out, will number them automatically, and will add a table of contents at the top of the page. (For most extensions, the documentation will be short and sweet, and this would just be clutter: headings and subheadings are best used only where the text would otherwise be difficult to read.)
Any extension's documentation can contain Examples, just as the main Inform documentation does: these are automatically labelled A, B, C, … rather than given numbers, to ensure that they do not clash with the numbering used in the built-in chapters. (The labels may be helpful in writing an extension's documentation: we can write, for instance, a note such as "see Example C below".)
Examples must be given last in the documentation, and there can be up to 26 of them, though most extensions will need one example at the most, and some will have none at all. Each example must begin with a paragraph exactly like so:
Again, there must be a skipped line before and after. The row of asterisks must be *, **, *** or ****, just as in the main documentation, which we should follow on all points of style. The rest of the line contains the title, a hyphen, and then the description. The title should be given with Each Word except Prepositions and Similar Things Capitalized, while the description should look like a sentence, and end with a full stop.
The text of the example follows, of course, and continues until the end of the file, or the next "Example:" line, whichever comes first.
Each example should (normally) contain one single, complete, story, long enough to demonstrate the use of the extension and to have a little flavour to it, but not so long that the reader gets lost. It should have a title, which should match the name of the example (in the case above, "We Must Perform a Quirkafleeg"). It should conclude with a paragraph defining a test:
The idea is that typing one single command, TEST ME, into the resulting story should show off what the extension does.
When an extension contains more than one example, they should be given in order of asterisk rating, that is, starting with the * examples, then the ** examples, and so on up.
Extension documentation can provide "paste" buttons, much like the examples in this book. For example:
Note that the paste button, denoted "*:", pastes in the text following it, but only as far as the next paragraph of unindented documentation – here, the one beginning "If we…". (But of course, an extension can have multiple paste buttons if desired.)
Extensions often need to define new kinds or properties, which we want to make as helpful as possible for the user. In particular, we want them not to require additional work for the author just to obtain the effect which seems only natural.
For example, consider Inform's built-in "locked" property. If a door is locked, then it cannot be opened, which seems fair enough. But if the player tries to unlock the door, he might then find the following response:
Which does not seem right. In real life, almost all locked items have outwardly exposed locks which it is perfectly sensible to try to unlock, given a key. The problem is that our door has the "locked" property, but not the "lockable" one.
The Standard Rules solve this problem by including the following line:
This ensures that any door said by the author only to be "locked" will be "lockable" as well, and adds a small but worthwhile touch of realism.
Such a sentence is called an "implication", as it is in the form "Condition A implies Condition B". Note that the two conditions must consist of either/or properties with or without kinds attached. Thus:
will not work because "a room in the Open Desert" is a more complicated grammatical construction than, say, "lighted" or "a lighted room": it contains a relative clause. Inform can only deal with simple implications.
Inform never overrides certainties with mere implications, and is cautious about allowing them to build overly long chains of argument. This is to prevent the following kind of difficulty:
Implications work just the same for values which aren't objects, so:
results in red being zesty, but blue and green being flat; blue because the source text explicitly says so (which trumps the "usually"), and green because this isn't a bright colour, so the implication doesn't arise.
Implications have not been mentioned up to now since they are only really needed by extensions, but also because they can be tricky, with unforeseen consequences. We should handle them with care.
The current Inform, "Inform 7", had a low-level precursor unsurprisingly called Inform, which ran through versions 1 to 6. What made Inform 6 low-level was that its style of coding was much more like traditional programming: it reads as a simple form of C, or an elaborate form of assembly-language, but with some interactive fiction tweaks.
That language is still used inside today's Inform project as a way to express very low-level operations. What happens to code like that is now very different (it is compiled into Inter, an intermediate-level representation used inside Inform, and no longer by the Inform 6 compiler). But the notation is the same, and the practical effect is that it is as if we are writing I6 code.
The final sections of this chapter show how such I6 code can be mixed directly in with natural-language source text. The remaining pages will therefore make little or no sense to those who do not already know I6 notation, and in any case, such programming is really a last resort – it is always best to write regular source text than to resort to so-called "inclusions" of I6. Ideally, all I6 content would be confined to extensions (and this may be mandated in future releases of Inform), and even writers of extensions are asked to pare down their usage of I6 to the minimum necessary.
The methods for incorporating I6 code into I7 have been designed with this in mind, that is, to encourage people to use I6 in as self-contained a way as possible: in particular to isolate the relatively few functions which need to be written in I6, and to give them natural language expression.
Finally, anyone hacking with I7 for a while is likely to become curious about the Basic Inform or Standard Rules extensions, and to look at the text which sets up the Inform language and world model. These extensions are, of course, no secret, but can be misleading to read. For one thing, they appear to have great freedom to set up the world model as it pleases, but in fact the I7 compiler may well crash unless certain things are done just so in the Standard Rules: they depend on each other.
Moreover, the Basic Inform and Standard Rules extensions use a number of syntaxes which are not documented in this chapter: these are constantly being altered, and it would not be safe to imitate them. Any I6-related syntax which is not documented in this chapter may be removed or changed in effect at any time without warning, for instance in an update of Inform to fix bugs.
The phrases described in this documentation, such as "end the story", are all defined in the Standard Rules, and are for the most part defined not in terms of other I7 phrases but instead reduced to equivalents in I6. For instance:
The notation "(-" and "-)" indicates that what comes in between is I6 code. The minus sign is supposed to be a mnemonic for the decrease from 7 to 6: later we shall use "(+" and "+)" to go back up the other way, from 6 to 7.
When a phrase is defined as containing only a single command, and that command is defined using I6 – as here – it is compiled in-line. This means that the phrase "end the story" will always be translated as "deadflag=3; story_complete=false;", rather than being translated into a call to a suitable function whose only statement is "deadflag=3; story_complete=false;".
This is an easy case since the wording never varies. More typical examples would be:
When the braced name of one of the variables in the phrase preamble appears, this is compiled to the corresponding I6 expression at the relevant position in the I6 code. So, for instance,
might be compiled to
because "{something}" is expanded to "capacity of the basket" (I7 code) and then translated to "O17_basket.capacity" (I6 code), which is then spliced into the original I6 definition "print {something};".
Braces "{" are of course significant in I6. A real brace can be obtained by making the character following it a space, and then I7 will not attempt to read it as a request for substitution.
It's also possible for the pair of characters "-)" to occur in I6 code, for example here:
and I7 will read the "-)" as terminating the I6; we can get around this with an extra space:
Warning: Inform 6 uses a restricted character set, allowing use of most of the accented characters in ISO Latin-1 (those found in a set called ZSCII) but little beyond that. It's therefore hazardous to use any exotic Unicode characters in an inclusion.
There are basically three forms of phrase in I7: phrases which do something, but produce no value or opinion as a result; phrases to decide whether or not something is true; and phrases to decide on a value. We have already seen examples of writing the first form in I6:
Here the I6 form is required to be I6 routine code in void context, that is, it will normally be one or more statements each of which ends in a semicolon (unless there are braced code blocks present). In this case, we have just one I6 statement, ending in a semicolon.
An example of a phrase to decide whether something is true would be:
Here the I6 code providing the definition must be a valid I6 condition, and be in round brackets, but there is no semicolon.
Lastly, an example of a phrase to decide on a value:
Again, this is a value in I6 as well: no semicolon. It is probably safest to place the value in round brackets.
The Standard Rules use the Inform list-writer with the following definition, which shows how a much more complicated I6 routine can be given a natural-language expression.
This can be used by, say:
"{phrase options}" is a special substitution: it is a bitmap which assigns the given options one bit each, starting with the least significant bit for the first-mentioned option ("with newlines" above) and going up to the most significant bit for the last ("with extra indentation").
Use options (see Chapter 2 above) manifest themselves in the I6 code generated by I7 as constants which are either defined, or not. For instance, the "use American dialect" option results in the constant DIALECT_US being defined, a constant which otherwise would not be. Some use options define the constant as a particular value, others simply define it (so that I6 gives this constant the value 0).
New use options can be created as in the following examples, which are found in the Standard Rules:
Most Inform users will not need to test whether a use option is currently set: after all, they will know whether or not their own story uses American dialect. But an extension does not know what use options apply in the story which is using it. An extension which needs to print a list, using its own formatting, might want to know whether "use serial comma" is set. Or it might want to speak differently in American dialect.
To test for American dialect, we should ideally not use I6 to look for the constant DIALECT_US using #ifdef: there is no guarantee that this constant will not be renamed at some point. Instead we can perform the test directly in I7:
and similarly for all other named use options. The adjectives "active" and "inactive" have the obvious meanings for use options. This means it's possible to describe the current options like so:
The result might be, say,
This may be useful for testing purposes.
Use options can also allow the writer to raise certain maximum values. If we write an extension which needs some I6 array, say, and therefore has some limitation – for instance a footnotes presenter which can handle at most 100 footnotes before its array space runs out – it would obviously be cleaner to allow this maximum to be raised. We can set this up like so:
With such a definition, the number given is the default value, and the I6 source is included whether or not anybody uses the option: the default value being given if nobody does. The text "{N}" is replaced with the value. So the above definition normally results in this being defined:
but if the user writes
then instead the I6 inclusion becomes:
The I6 constant MAX_PRESENTED_FOOTNOTES can then be used as the size of an array, for instance.
Finally, note that it is legal to define the same use option more than once, but only if it has exactly the same meaning each time it is defined. (This is allowed so that multiple extensions all needing the same definition can safely make it, and still be used together.)
Whole routines, object and class definitions (or any other directives) can be pasted in wholesale using sentences like so:
Such inclusions are pasted into the final compiled code at the end of the file, after the I6 grammar has been declared.
In such extracts, we sometimes need to refer to objects, variables or values which can't be described using I6: or rather, which can be described, but we don't know how. To this end, any text in an inclusion written in "(+" and "+)" parentheses is treated as an I7 value, and compiled accordingly, with all type-checking waived for the occasion. For instance:
Here "the tartan rucksack" is translated into "O18_tartan_rucksack", or something similar: the I6 object created to represent the rucksack. Thus the actual line of code produced is
The material between "(+" and "+)" is generally treated as a value, and thus compiles to the I6 form of that value. But it could also be a property name, which compiles to the I6 form in question, or a defined adjective, which compiles to the name of the routine to call which tests whether that adjective is true.
Three warnings. The material in "(-" and "-)" is not quite treated as literal. Certain characters cause Inform to react:
1. Beware of accidental "(+" usage – for instance,
looks reasonable, but contains "(+" and "+)". Spaces around the first "++" would have been enough to avoid this one; "+)" is only significant where it follows a "(+".
2. Beware of placing an "@" character in the first column, that is, immediately following a new line. (In template code this marks off paragraph divisions.) So for instance,
is tripped up by the Glulx assembly language opcode "@glk" because this occurs in column 1. Indenting it with a little space or a tab is enough to avoid the problem.
3. Be careful if you're creating an I6 variable holding initialised I7 text. For example,
looks as if it will work, but doesn't, for reference-counting reasons we needn't go into; instead you need
But it's far better to avoid initialising text variables from I6 entirely. The same problems arise with constant lists.
It should also be noted that the I6 syntax recognised inside "Include (- … -)" is slightly restricted compared to the full range recognised by the stand-alone Inform 6 compiler. In particular:
1. Only new-style "for" loops with colons in the header are allowed, so that "for (i=0: i<10: i++)" is okay but "for (i=0; i<10; i++)" is not. Moreover, "for" loops cannot contain empty clauses.
2. Local variable names are not allowed to be the same as an I6 statement keyword: for example, "style" and "spaces" are not allowed.
3. The (undocumented) Inform 6 function "indirect()" is not supported. But since "indirect(A)" is equivalent to "A()", which does work, this is no real loss. Similarly, the "glk()" function is not supported: function calls to BasicInformKit should be used instead.
4. Conditional compilation cannot be placed around cases in a "switch" statement.
5. Compile-time constant expression evaluation can be used with arithmetic operations, so "Constant FOO = BAR + 1;" is okay, but not with bitwise or logical operations, so "Constant FOO = (BAR | 1);" does not work.
6. Calculated values cannot occur as assembly-language operands.
7. Calculated values can be used for array extents, but need to be put in brackets. For example:
By writing a sentence like this:
we create a new rule, the "underground rule", and also notify Inform that it will have no definition as I7 source text: instead, it will be provided as an I6 routine called "UNDERGROUND_R". We can define this with an Include like so:
The rule should return false if it wants to make no decision, but call either RulebookSucceeds or RulebookFails and return true if it does. These routines can optionally take an argument: which will be the return value from the rulebook.
Note that UNDERGROUND_R itself has no arguments. In the case of an action based rulebook, the I6 variables noun, second and actor can be referred to, while for a value based rulebook the parameter is stored in the I6 global variable parameter_object (which is not necessarily an object, in spite of the name).
We can put this rule into a rulebook in the same way that any named rule can be:
As might be expected, I7 compiles an I6 class for each kind, and an I6 object for each of its own objects. We can meddle with its compilation process here using a further refinement of Include. For instance, suppose we want the I6 class definition for things to come out containing a property like this:
How to arrange this? One way is to create an ordinary I7 property, like so:
(Without that last sentence, the property won't get any familiar name.) But sometimes we need more, and want to actually write new material to go into the definition. This can be done like so:
This glues in a new property to the class compiled to represent the I7 kind "vehicle". (See the DM4 for why. However, since the entire actions machinery is different in the I7 world, note that "after", "react_before" and "react_after" no longer have any effect, and nor does "before" for rooms.)
And similarly:
If we need a particular I7 object or kind to end up with a particular I6 name, we can write:
WARNING: The "Include (- … -) when defining …" usage still works for the moment (except in projects compiled to C at the command line, where it may fail), but it is deprecated and likely to be removed in later versions of Inform. Avoid it if at all possible.
I7's variables are usually compiled as entries in an array rather than as I6 variables. However, we can instead tell Inform to use an existing I6 variable (either one that we declare ourselves, or one in the I6 template layer). For example:
This is a feature provided to help I7 source text to use variables internal to the I6 template code. It can, if really necessary, also be used to give I7 names to entirely new I6-level variables, created like so:
This style of hybrid coding is really not encouraged.
I7's properties are compiled sometimes as I6 properties, sometimes as I6 attributes, sometimes as bits in a bitmap somewhere. However, we can override I7 by telling it that one of its property names is equivalent to an already-existing I6 property or attribute: if so then I7 will use that name and will not compile any directive to create it. For example:
We do not need to translate "switched off", the opposite to "switched on": I7 will now compile this to "~on".
Lastly, actions can also be translated (though it's usually better to translate their rules instead and invent new I7 actions covering them):
The parser which deciphers the player's typed commands is written in I6, and many of the basic tokens of Understand grammar are implemented as "general parsing routines" (GPRs), the specification of which is described fully in the Inform 6 Designer's Manual. I7 translates much of the source text's Understand grammar into GPRs, and once again we can bypass this process and supply an Understand token directly as an I6 GPR. For example:
We then have to include a routine of that name into I7's output using the "Include" instruction, on which more later.
This creates a token "[squiggle]"; so for instance if the source text contains:
then Inform would parse the command COPY FIGURE EIGHT by calling the SQUIGGLE_TOKEN routine as a GPR with the word marker at 2, that is, at the word FIGURE.
As always, this should be done only where there seems no better way, or where speed is very important. For any fairly simple range of possibilities, it's better to use the techniques in the Understand chapter, or to use unit specifications.
There are three ways to specify that an adjective is defined at the I6 level. For example:
Inform now actually tests if a number N is prime by calling PRIMALITY_TEST(N), and it assumes that we have also included such a routine in the output. The routine is expected to return true or false accordingly.
The text in brackets does nothing functional, but is the text used in the Lexicon dictionary part of the Phrasebook index for the user's benefit; it should be a brief definition. Extension authors are asked to provide these little definitions, so that their users won't be confused by blank lexicon entries.
The second way makes a more capable adjective, since it can not only be tested, but also made true or false using "now". For example:
The difference here is "makes it so", not "says so", and as this implies, the routine has more power. "SceneCrucial" is called with two arguments: SceneCrucial(S, -1) tests whether the scene is crucial or not and returns true or false; SceneCrucial(S, true) must make it true; and SceneCrucial(S, false) must make it false. Another useful difference is that if the kind of value is one which is stored in block form (e.g. for an adjective applying to text), the routine is given a pointer to the block, not a fresh copy.
A third way to define an adjective, which should be used only if speed is exceptionally important, is to provide a "schema" – a sort of I6 macro, like those provided by the C preprocessor. For example:
The escape "*1" is expanded to the value on which the adjective is being tested. (This is usually faster than calling a routine, but in case of side-effects, the "*1" should occur only once in the condition, just as with a C macro.) To repeat: if in doubt, use the I6 routine method above.
Inform allows the Unicode characters to be identified either with a decimal number or by name, but it has none of the character names built-in, and for efficiency reasons it only learns them when necessary.
Users normally teach these names to Inform by including one of the extensions "Unicode Character Names" or "Unicode Full Character Names", which consist of many hundreds of sentences like so:
Nothing restricts this usage to those extensions.
When Go is clicked, Inform translates the I7 source text into a large body of so-called "Inter" code: "Inter" is short for "intermediate". Large as this program is, it could not survive on its own: it needs a large body of pre-compiled code, also written in Inter, to sustain it. This additional material is organised in blocks called "kits". Most Inform users never need to know about kits, but for example, a typical Inform project includes kits called BasicInformKit, WorldModelKit and CommandParserKit.
These kits are compiled from what is (nearly) Inform 6-syntax source code, and for the details of that, see the documentation on the low-level tool "inter". While it's absolutely possible for Inform users to create and use their own kits, that's beyond the scope of this book. But what we will cover here is the ability to include just a little extra Inter code – perhaps only a few functions or constants.
In fact, we have seen the necessary syntax already:
puts the given material "…" into the project. For example:
adds just a single function called "ExtraFunction".
And this works fine, but if we tried the same trick to create a function called "SquareRoot", for example, then the result would be a problem message – because BasicInformKit also defines a function of the same name. This problem message is useful, because it warns us about accidental name clashes.
But what if the name clash was not an accident at all, and what we actually wanted to give our own definition of "SquareRoot", to be used instead of the one in BasicInformKit? This is also possible:
And now whenever square roots are calculated, this snarky text will be printed, and the result will always be rather meaningless (since this I6 routine always returns 1). Unless one is very careful, the result of replacing kit definitions can be absolute chaos.
An important historical note: between about 2010 and 2021, kits did not exist, and instead there were "template files" of Inform 6 code which served roughly then same purpose. These had names like "Relations.i6t" or "Mathematics.i6t" and were internally divided into named subsections; and Inform supported syntax like the following:
to allow new material to be placed at oddball positions in the final code. There is now no need to worry about the placement of code – Inform's final code generator manages things so that code-ordering issues do not arise; as a result, the "before" and "after" options are now unnecessary. For now, Inform ignores these usages, and just disregards the "before…" or "after…" parts. But in some later version of Inform they will begin to cause problem messages, so writers of extensions using these syntaxes should now please remove them.
The "instead of" option now cannot work at all, and throws a problem message. The new way to substitute a fresh definition of something built-in is to use the "replacing" notation described above.
With the demise of the "template layer", as it was called, another form of so-called "template hacking" has gone with it – the special notation:
to allow a whole extra file of Inform 6 code called "MyStuff.i6t" to be pasted in. The new way to do that is to create a new kit, say MyStuffKit, to hold the material in question. This is not hard to do, but beyond the scope of this book. See the documentation on the low-level Inform tool "inter".
The "language of play" is the natural language used to communicate with the player at run-time: this is normally English.
That means that it is difficult to write, say, Spanish-language IF using Inform 7, though heroic work by the Spanish IF community has overcome this. Inform 6 provided for translation by isolating its linguistic code in a part of the I6 library called the "language definition file", which was normally "English.h". Translations were gradually made to most major European languages, resulting in alternative language definition files called "French.h", "Italian.h" and so on. Full details on how to write a language definition file were given in the Translations chapter of the DM4, that is, the fourth edition of the Inform 6 Designer's Manual.
In I7 the system is different. We use the template, not a library. Instead of providing a language definition file such as "French.h", a translator should create an extension called something like "French Language by Jacques Mensonge". (The language should be named in English, so "French Language by …", not "Langue français by …") This extension should then contain broadly the same material as an I6 language definition file, but written in a mostly higher-level way. See the extension "English Language by Graham Nelson" supplied with I7, which is included automatically by default.
A "segmented" substitution is a syntax where text is placed between two or more different text substitutions. Examples include:
To create such syntaxes, it is not enough just to define how each expands into I6 code: for one thing we may need to know about the later terms in order to expand the earlier ones, which is normally impossible, and for another thing, the individual text substitutions mean nothing in isolation. For instance, Inform produces a problem if the following is tried:
because "[at random]" is only legal when closing a "[one of] …" construction. But if "[at random]" had been defined as just another text substitution, Inform would not have been able to detect such problems.
Inform therefore allows us to mark text substitutions as being any of three special kinds: beginning, in the middle of, or ending a segmented substitution. There can be any number of alternative forms for each of these three variants. The syntax policed is that
A simple example:
This creates "[emphasis on]" and "[emphasis off]" such that they can only be used as a pair. The keyword "say_emphasis_on", which must be a valid I6 identifier (and hence a single word), is never seen by the user: it is simply an ID token so that Inform can identify the construction to which these belong. (We recommend that anybody creating such constructions should choose an ID token which consists of the construction's name but with underscores in place of spaces: this means that the namespace for ID tokens will only clash if the primary definitions would have clashed in any case.)
The process of expanding the I6 code which represents a phrase is called "invocation". As we have seen, when a phrase is defined using a single piece of I6 code, invocation consists of copying out that I6 code, except that tokens in braces "{thus}" are replaced:
Ordinarily the only token names allowed are those matching up with names in the prototype, as here, but we have already seen one special syntax: "{phrase options}", which expands as a bitmap of the options chosen. And in fact the invocation language is larger still, as a skim through the Standard Rules will show. The notes below deliberately cover only some of its features: those which are likely to remain part of the permanent design of Inform, and which are adaptable to many uses. Please do not use any of the undocumented invocation syntaxes: they change frequently, without notice or even mention in the change log.
The first special syntaxes are textual tricks. {-delete} deletes the most recent character in the I6 expansion of the phrase so far. {-erase} erases the I6 expansion of the phrase so far. {-open-brace} and {-close-brace} produce literal "{" and "}" characters.
The following:
create (if one does not already exist) a counter called NAME. This is initially zero, and can be reset back to zero using "{-zero-counter:NAME}", which expands into no text. The token "{-counter:NAME}" expands into the current value of the counter, as a literal decimal number. The token "{-counter-up:NAME}" does the same, but then also increases it by one. Finally, the token "{-counter-makes-array:NAME}" expands to nothing, but tells Inform to create an "-->" array called "I7_ST_NAME" which includes entries from 0 up to the final value of the NAME counter.
This allows each instance in the source text of a given phrase to have both (i) a unique ID number for that invocation, and (ii) its own word of run-time storage, which can allow it to have a state preserved in between times when it is executed. For example:
To complete the tools available for defining a segmented substitution, we need a way for the definition of the head to know about the middle segments and the tail:
When invoking either the head or the tail, {-segment-count} expands to the literal decimal number of pieces of text in between the two, which is always one more than the number of middle segments, since the text comes in between the segments. When invoking any middle segment, {-segment-count} expands to the number of pieces of text so far -- thus it expands to 1 on the first middle segment invoked, 2 on the next, and so on.
Lastly {-final-segment-marker} expands to the I6 identifier which marks the end segment, or to I6_NULL if the end segment has no marker. The idea of markers is to enable the head's definition to know which of a number of choices has been used for the tail, supposing that this is a construction with a variety of legal endings. For example:
The markers used for the tails here are "underline" and "fixed", and when the head is invoked, the marker for its tail is expanded into the argument of I6's "style" statement.
The examples above are all to do with segmented substitutions, which is where they are most useful, but most of the syntaxes above work equally well for ordinary "To…" phrase definitions.
Many of the invocation syntaxes described in the previous section are used in the definition by the Standard Rules of the "[one of] … [or] … [purely at random]" construction, so it makes a good example of how they can be used.
First, this is a segmented substitution with a single possible beginning ("[one of]"), a single possible middle ("[or]") but a choice of many possible endings. Almost everything is compiled by the invocation of the beginning:
The 3rd invocation of this (say) might compile the following:
First, we notified Inform that it needs to allocate an array (I7_ST_say_one_of) providing storage associated with the counter "say_one_of". This we used to count off individual invocations of "[one of]", so that each would have its own word of storage – for the 3rd invocation, I7_ST_say_one_of-->2. We then call a state-changing routine, in this case I7_SOO_PAR, which is allowed to know the previous state and also the number of options available, and which returns the new state. The state is supposed to be the option chosen last time, but that means that there are not 4, but 5 possibilities: 0 for "there was no last time", then 1 to 4 for the possible outcomes. We reduce the state mod 5 to obtain the decision this time, and subtract 1 because it happens to be convenient to make the switch statement run from 0 to 3 rather than 1 to 4. (The reason we reduce the state mod 5 is to allow the state-changer to squirrel away secret information in the upper bits of the state, if it wants to. Note that subtracting one means that the switch value might be -1, which results in no text being printed: thus if the state-changer chooses 0, it can decide on none of the above.)
In this design, the marker attached to the choice of ending substitution is the name of the I6 state-changer: here is the I7_SOO_PAR routine.
As it happens, this ignores the old value: after all, it is meant to be purely at random, and nothing could be less pure than taking the last outcome into consideration when choosing the next.
Note that the counter say_one_of is advanced in invocation of the head. It might seem that the tidier design, somehow, would be to advance the counter in the invocation of the tails, but this is not a good idea. In general it is not safe to assume that the counter will have the same value when the tail is invoked that it had when the head was invoked, because segmented say constructions can legally be nested in Inform strings. Because of this, it is best to deal with a counter entirely in a single invocation, either of the beginning or the ending.
Because "[one of] … [or] …" is such a useful construction – switching between alternative forms of text, which writers of IF very often do – the above implementation is intentionally left open for new endings to be added, and the examples below show how easily this can be done.
The Inform Recipe Book is one of two interlinked books included with Inform 7: a comprehensive collection of examples, showing the practical use of Inform. The other book is Writing with Inform, a systematic manual for the software.
The Recipe Book assumes that the reader already knows the basics covered in Chapters 1 and 2 of Writing with Inform: enough to get simple projects working in the Inform application. It's helpful, but not necessary, to have some familiarity with the main ingredients of Inform. For instance, the reader who can play and test the following source text, and who can take a guess at what it ought to do, should be fine:
The Recipe Book is not a tutorial – it offers advice and examples to crib from, not theory or systematic teaching. The examples here are provided with the express intention that authors cut and paste useful passages into their own works, modifying as they go. This is an excellent way to get things working quickly.
In the traditional saying: good programmers write good code, but great programmers steal it. (Appropriately enough, nobody seems to know who said this first.) For the avoidance of any doubt – the example text is here to be taken, and this infringes no copyright, and requires no acknowledgement. So steal at will. The examples are a part of Inform itself, and as such, they are available to anyone who accepts the Inform licence.
Many programming languages for conventional computing, such as C, come with elaborate libraries of ready-written code – so elaborate, in fact, that they often need much larger manuals than the language itself, and can be hard to learn. Even expert programmers typically use only a small part of what is available in such libraries, giving up on the rest as too complex to use, or too difficult to find out about, or not quite what they need.
The designers of Inform chose not to go down this road. Rather than providing a general system for liquids (say), which would have to be a quite complicated and opaque program, Inform provides a choice of examples showing how to get different effects. The writer can read the text which achieves these effects, and can simply cut and paste whatever might be useful, and rewrite whatever is not quite wanted.
The wider community of Inform writers has made a great wealth of material available in the form of Extensions, too, and under a Creative Commons Attribution licence requiring only a namecheck: we don't cover the Extensions in this book, because it would grow far too long and be a constant labour to maintain, but it's well worth seeing what is out there.
Acknowledgements for a chance to try out the cross-referencing links in the Recipe Book - click on the red asterisk or the name of the destination to go there.
This is the first of about 400 numbered examples. In a few cases, such as this one, they provide a little background information, but almost all demonstrate Inform source text. The techniques demonstrated tend to be included either because they are frequently asked for, or because they show how to achieve some interesting effect.
The same examples are included in both of the books of documentation, but in a different order: in Writing with Inform, they appear near the techniques used to make them work; in The Inform Recipe Book, they are grouped by the effects they provide. For instance, an example called "Do Pass Go", about the throwing of a pair of dice, appears in the "Randomness" section of Writing with Inform and also in the "Dice and Playing Cards" section of The Inform Recipe Book. Clicking the italicised WI and RB buttons at the right-hand side of an example's heading switches between its position in each book.
Many computing books quote excerpts from programs, but readers have grown wary of them: they are tiresome to type in, and may only be fragments, or may not ever have been tested. The authors of Inform have tried to avoid this. All but two dozen examples contain entire source texts. A single click on the paste icon
(always placed just left of the double-quoted title) will write the complete source text into the Source panel. All that is then required is to click the Go button, and the example should translate into a working game.
In most cases, typing the single command TEST ME will play through a few moves to show off the effect being demonstrated. (You may find it convenient to create a "scratch" project file for temporary trials like this, clearing all its text and starting again with each new test.)
As part of the testing process which verifies a new build of Inform, each example in turn is extracted from this documentation, translated, played through, and the resulting transcript mechanically checked. So the examples may even work as claimed. But the flesh is weak, and there are bound to be glitches. We would welcome reports, so that future editions can be corrected.
Each example is loosely graded by difficulty: if they were exercises in a textbook, the asterisks would indicate how many marks each question scores. As a general rule:
In general, the main text of Writing with Inform tries never to assume knowledge of material which has not yet appeared, but the trickier examples almost always need to break this rule.
12. ★ Midsummer DayDavid Fisher's "Past raif topics" pages on the Interactive Fiction Wiki were an invaluable tool during the early design of these examples, as they catalog an enormous assortment of implementation problems encountered by IF authors over the past fifteen years.
Thanks also go to Nick Montfort for several conversations during the development of Inform: these inspired a number of ideas about how the author should be able to control the textual output of a story, and suggested specific problem areas to work on.
Jeff Nyman provided extensive feedback about using Writing with Inform in workshops of aspiring IF authors from both programming and conventional fiction writing backgrounds. His observations about the concerns of conventional writers first encountering IF were especially useful, and had a great influence on the organization of the Recipe Book. While the results may not meet all the needs he identified, we hope to have taken a step in the right direction.
A few examples were contributed by denizens of rec.arts.int-fiction: Jesse McGrew, Jon Ingold, Mike Tarbert, Eric Rossing, and Kate McKee offered such elegant implementations of various tasks that we have folded their contributions (with permission) into the Recipe Book.
Finally, these pages owe much to the questions and suggestions of Inform users on rec.arts.int-fiction and ifMUD.
"Disenchantment Bay" is a simple work of IF used as a running example in Chapter 3 of Writing with Inform – not so much a tutorial as a convenient hook on which to hang some demonstrations of the basics. Because the resulting examples only use basic features and in the most straightforward way, they make for uninteresting "recipes" – so they are not included in the Recipe Book proper. But some readers might like to have all twelve stages of the example gathered on a single page: this is that page.
To begin with the title:
There are many Disenchantment Bays across the world, named by eighteenth-century ships' captains – one in Antarctica, another in Tasmania, for instance. The most famous is probably the one where Lewis and Clark's expedition broke through to the Pacific. But ours is the one in Alaska, named in 1791 by a Spanish navigator who had hoped it might lead to the fabled Northwest Passage, and all of this history is beside the point since the game is set in the present day.
We might want to start with the glass case.
Now Inform will have guessed that the case is a container, but its default idea of a container is something like a bucket: permanently open and not able to be opened and shut. We can change that:
We get a similar set of guesses if we write
Using "some" rather than "a" or "the" tells Inform that the cushions are to be referred to as a plural object in the future. And because of the "on the bench…" phrase, Inform will guess that the bench is a supporter and that it is fixed in place and cannot be moved from room to room. We do have to tell it that the bench can be sat on, though:
And now a short script, so that if we type TEST ME, we experiment with the case and bench:
If we compile our last version of the cabin, we get a room where the glass case and the bench are listed separately from the room description, even though they have already been mentioned once. We can prevent this by making the already-mentioned things scenery:
Generally speaking, it is a good idea to recognize the player's attempts to interact with any objects mentioned in the room description, so we should also provide
The door and the view will need to be done as well, but they are special cases which we will get to shortly.
As noted, making something scenery also means that the player will be prevented from picking it up and carrying it away. This is sensible, though: if an object can be removed from the room where it first appears, we should be careful about mentioning it in the main room description; otherwise, it will continue to be described as present even when someone has carried it off.
17. ★ Disenchantment Bay 3Suppose we wanted to have the glacier visible from the Cabin of our boat, and anywhere else we might add to the game:
Currently we have provided objects for most of what is on the boat, but it's not very interesting to look at. We might want to give some more description to these things.
The order in which we define these things is fairly open. We could also define an object so:
Where "the description" is assumed to refer to the thing most recently defined, if no object is specified.
These last two commands show how scenery and backdrops are automatically impossible for the player to take.
20. ★ Disenchantment Bay 5We mentioned that there is a door out to the deck in our example. The following two sentences will create both the door and the other room:
Now Inform has constructed a generic room called "Deck" to the south. It has neither a description nor any contents yet, but we could fix that in time. It does have a view of the glacier, though, since we defined the glacier view to be everywhere.
23. ★ Disenchantment Bay 6It stands to reason that the captain wouldn't let just anyone meddle with his fishing equipment; maybe he keeps that case locked. We could replace the case description with this one, instead:
Now there's a silver key that will unlock it -- though since we haven't said where the key is, the player will never be able to find it in the game. (If we look at the World index, we find "small silver key" right at the bottom, not inside any of the rooms. That is as good as not existing at all -- though we usually use the term "out of play" -- but as we will later see, it is possible to have things initially out of play but brought into existence later on.)
25. ★ Disenchantment Bay 7If we would like the player to be able to turn instrumentation on and off, we could add a line to this effect:
And since the captain is probably not navigating blind, we might also want to say
Now finally we can put a Captain in the boat:
At this point we can dress both the Captain and the player with some appropriate props:
(At present the backpack can't be worn, but see the next version.)
34. ★ Disenchantment Bay 11If we wanted, we could make the player's backpack infinitely capacious, so:
…And now whenever the player character is unable to hold everything, he will automatically stow some of his possessions therein.
This is only useful if the player doesn't have infinite carrying capacity himself, so perhaps we also need
Perhaps mercifully, items which are worn are not counted against the player's carrying capacity. We might want to let him take advantage of that, too:
This capacity system makes a compromise between the realistic and the absurd: on the one hand, it acknowledges that people can't carry an infinite number of items in their hands, while at the same time providing a sack that can.
Many games will have no use for object-juggling of this kind at all; others will want to be much more rigorous about questions of capacity and volume. Fortunately, it is easy to leave the whole business out by assigning no carrying capacity to anything.
28. ★★ Disenchantment Bay 8We probably do not need a vehicle to ride around our boat, but there might be a heavy ice chest that can only be pushed from room to room:
This anticipates a later chapter, but it would probably be a good idea to hint to the player, if he tries to take the ice chest, that there is another way to move it:
Otherwise, attempts to pick it up will just reply with "That's fixed in place."
37. ★★★★ Disenchantment Bay 12One last preliminary: a handful of the examples do not show how to do anything at all, but are really sidebars of information. Those examples are gathered below, since they contribute nothing by way of recipes.
There is not really any unanimity about what regular expression language is. The unix tools sed and grep extend on Kleene's original grammar. Henry Spencer's regex library extended on this again, and was a foundation for Perl, but Perl once again went further. Philip Hazel's PCRE, despite the name Perl Compatible Regular Expressions, makes further extensions still, and so on.
Inform's regular expressions are modelled on those of Perl, as the best de facto standard we have, but a few omissions have been inevitable. Inform's regex matcher must occupy source code less than one hundredth the size of PCRE, and it has very little memory. Inform aims to behave exactly like Perl except as follows:
Inform further does not support the Python extension of named subexpression groups, nor the Java extension of the possessive quantifier "++". There was only so much functionality we could squeeze in.
As verification of Inform's matching algorithm, we took the Perl 5 source code's notorious "re-test.txt" set of 961 test cases, removed the 316 using features unsupported by Inform (220 tested multiline mode, for instance), and ran the remaining 645 cases through Inform. It agrees with Perl on 643 of these: the two outstanding are -
Case (i) is a sacrifice to enable Inform's back-tracking to use less memory. Case (ii) simply seems unimportant.
223. ★★★ Formal syntax of sentencesAn entire grammar for the whole mass of Inform would not be linguistically interesting: it contains many convenient wordings which are not really part of a grand pattern. Inform does, however, have a formal notion of a Sentence, a grammatical structure which we shall call S. It is almost true that conditions ("if the flowerpot is on the wall") have the same grammar as assertions ("The flowerpot is on the wall") and "now" phrases ("now the flowerpot is on the wall"). All three use the S grammar, so we could define an assertion as "S.", say that "if S", "while S", "when S" and so on are conditions, and say that "now S" defines the "now" declaration.
Grammatical sentences do not necessarily make sense, of course. Many perfectly grammatical assertions in fact give rise to problem messages:
Whereas the first three, at least, would be sensible as conditions. So saying that assertions are "just like" conditions is a little misleading: what they have in common is S, the underlying grammar they each use as a starting-point.
To define S, we break it up into subsidiary structures. The most important is the Description Phrase (DP), examples of which include "the red basket", "somewhere lighted" and "an empty open container". Clearly sentences include DPs, but they also include other ingredients. The general pattern used in Inform is very simple:
where VP is another structure, the Verb Phrase. For instance:
In that example, the Verb was the single word "wears". More generally, Inform allows a Verb to include adverbs and prepositions, to be negated, and to come in any of four tenses, so the following are all valid examples of Verb in our grammar:
Although we are not going through the definition of Description Phrases in detail, it is worth noticing how "which" and "who" behave:
Thus "an open container which is in the Ballroom" can be broken down as:
To understand compounds like "something in a container", we have to invent a new grammatical structure for "in a container" and similar: let's call this a Relative Phrase (RP).
Thus "an open container in the Ballroom" is DP (an open container) + RP (in the Ballroom). Relative Phrases have two different forms:
so that "in a container" is an example of 5a. An example of 5b would be
That is nearly it, but not quite: we must go back to the "almost" in the statement above that assertions and conditions "almost" have the same grammar S. The difference arises from a curious irregularity in English called subject-verb inversion (see the Oxford English Grammar at 3.22F), whereby assertions can be reversed but not conditions. For instance,
This does not follow the pattern S = DP + VP, because "in the garden" is not a DP: indeed, it is not a noun at all. To make sense of this sentence, Inform reverses it to "A sunflower is in the Garden", which does indeed follow DP + VP. Hence the final rule:
So the condition "if in the garden is a sunflower…" fails because rule 6 does not apply to the grammar for conditions: while occasional poetic uses of subject-verb inversion do turn up in conditions ("If On A Winter's Night A Traveller", say), they are rare in ordinary English usage, and illegal in Inform. That completes the S grammar, so to recap:
Inform uses the term "relation" in a broader sense than mathematics. Properly speaking, the term "relation" in its mathematical sense only applies to the case where the domain for the left and right objects are the same: for simplicity's sake, let us talk only about the case where they are.
In mathematics, the properties most often looked for in a relation are that it should be:
(a) Reflexive: A <=> A for every A. This is not especially useful for Inform, and seldom appears in practical examples.
(b) Symmetric: A <=> B if and only if B <=> A. Generally, Inform relations are not symmetric, but there are two important cases which are:
These are automatically symmetric, so that to assert one way round is to assert the other as well.
(c) Transitive: A <=> B and B <=> C means that A <=> C as well. Again, Inform relations are not generally transitive. In many relations, there can be long chains of things, each perhaps related to the one in front and the one behind, so that there is some indirect sense in which the two ends of the chain are connected to each other: but they are not related as such. For instance, a journey across the map might pass through ten rooms, each adjacent to the last and next, but the two ends would not themselves be adjacent. The concept we need is the "transitive closure" of the original relation, defined as the smallest transitive relation including the original. If R is a relation between "things", then the following:
is the transitive closure of R. In particular,
calculates the transitive closure of adjacency. Here, though, the way we normally understand "accessible from" suggests that it would be better to write:
which is reflexive as well as transitive. The usefulness of Inform's "next step via R from A to B" construction, in a wide variety of settings, reflects the importance of transitivity as an idea.
A relation which has all three properties of being reflexive, symmetric and transitive is called an "equivalence relation". (If all the map connections are two-way, then the accessibility relation above is symmetric and therefore a full equivalence relation: but if not, it may not be.) Inform has a special construction for making equivalence relations:
This language – "in groups" – relies on the standard theorem that every equivalence relation on a set naturally defines a partition of that set, and vice versa. The "groups" referred to are what are normally called "equivalence classes". (Inform does little with these equivalence classes: it might be interesting to do so, in effect forming quotient kinds.)
244. ★★★ Graph-theory view of relationsOne way to look at a relation is to regard it as a directed graph: that is, a collection of things ("vertices") with arrows drawn between them ("edges"). We write our items A, B, C, … on a piece of paper: then, if A relates to B, we draw an arrow pointing from A to B, and so on. If we made this drawing for the adjacency relation, we would more or less have reconstructed the map (or at least a simplified one which does not care about precise directions, like the famous diagram of the London Underground). But the drawing can be made for any relation. If we define:
then, in the corresponding graph, each "vertex" will have at most one arrow leading away from it – though there could be many (or none) leading towards. Conversely, a one-to-various relation produces a graph where each vertex has at most one arrow coming in. A one-to-one relation means that the picture consists of some vertices on their own, with no arrows, a few perhaps with looped arrows leading from and to themselves, and then a collection of pairs joined by arrows. On the other hand, a various-to-various relation is just a free-for-all, with no restrictions on the arrows. The relations:
always have the property of working both ways round, and these are easiest to visualise by forgetting the direction of the arrows, so that they just become lines joining the vertices.
Inform uses a different algorithm for finding routes ("the next step via R from A to B") in each of these cases, and internally it stores relations in different formats in the different cases, because it makes a big difference to the efficiency of Inform to minimise the storage required for a relation and the time taken to explore it.
All the cases are benign except for "various to various" – the most useful – and for its closely related symmetrical version, "relates… to each other". Inform cannot afford to assume that the relation will be "sparse" (that is: that no vertex will have more than a certain number of arrows, or that the total number of arrows will be small), because it has no idea how the arrows will come and go during play. It therefore uses 1 bit of storage for each pair of objects. This sounds harmless, but if there are 200 rooms, there are 40,000 pairs of rooms, which means a 5000-byte allocation of storage (plus a handful of bytes as overhead). Gratuitous various-to-various relations are therefore not a good idea.
There is a standard algorithm for calculating shortest paths through a directed graph, but Inform does not always use it, because there is not always memory to store the required matrix of partial results. Inform's slow method, likely to be used on the Z-machine, requires a storage overhead which is equal to the number of vertices, not the square of that number, but the worst-case running time can be bad: if there are N vertices, and the diameter of graph (the longest distance between vertices) is D, then the running time is proportional to D times N. The worst case in finding routes from A to B is when almost every vertex can reach B, some across long trails, but A cannot. In the case of finding routes across the game's map, this must be multiplied further by the number of possible directions – usually 16.
This does not sound too awful, but if one is trying to find (say) "the most distant room from A", that means a further loop and now the running time will be D times N squared. Extension writers will need to be careful of this kind of thing: it is easy to write highly cool prototypes which work terribly slowly on larger, more realistic maps.
Before getting to actual recipes, many recipe books begin with intimidating lists of high-end kitchen equipment (carbon-steel pans, a high-temperature range, a Provencal shallot-grater, a set of six pomegranate juicers): fortunately, readers who have downloaded Inform already have the complete kitchen used by the authors. But the other traditional preliminaries, about universal skills such as chopping vegetables, boiling water and measuring quantities, do have an equivalent.
For us, the most basic technique of IF is to craft the text so that it smoothly and elegantly adapts to describe the situation, disguising the machine which is never far beneath the surface. This means using text substitutions so that any response likely to be seen more than once or twice will vary.
M. Melmoth's Duel ★ demonstrates three basic techniques: an ever-changing random variation, a random variation changing only after the player has been absent for a while, and a message tweaked to add an extra comment in one special case. (Random choices can be quite specifically constrained, as Ahem ★ shows in passing.) Fifty Ways to Leave Your Larva ★ and Fifty Times Fifty Ways ★★★ show how a generic message can be given a tweak to make it a better fit for the person it currently talks about. Curare ★ picks out an item carried by the player to work into a message, trying to make an apt rather than random choice. Straw Into Gold ★★★ demonstrates how to have Inform parrot back the player's choice of name for an object.
Another reason to vary messages is to avoid unnatural phrasing. Ballpark ★★★ turns needlessly precise numbers – another computerish trait – into more idiomatic English. (Likewise Numberless ★, though it is really an example demonstrating how to split behaviour into many cases.) Prolegomena ★ shows how to use these vaguer quantifiers any time Inform describes a group of objects (as in "You can see 27 paper clips here.").
Blink ★, a short but demanding example from the extreme end of Writing with Inform, shows how the basic text variation mechanisms of Inform can themselves be extended. Blackout ★ demonstrates text manipulation at a lower level, replacing every letter of a room name with "*" when the player is in darkness.
Inform's included extension Complex Listing allows us more control over the order and presentation of lists of items.
For how to change printed text to upper, lower, sentence, or title casing, see Rocket Man ★.
We can use these substitutions to put together fairly complicated variations within a single piece of text:
In this context, [denial] is understood to refer to the denial property of the noun -- but we could spell it out with "denial of the noun" if we wanted to.
And then it would be trivial to insert further rules using these responses:
As we see in the example here, it is possible to use slashed variations in more than one place in a phrase, and to offer a number of separate forms. The main rule of thumb to remember is that value inputs for the phrase should always be separated by some text; so
would cause a problem when we tried to call it with
In general, we probably don't need to make our phrase definitions quite so flexible as this, but it's a good idea to account for "a" vs. "the", and for the possibility of using singular and plural forms, especially when writing extensions or other source to be shared.
The final "otherwise" here will fire only if none of the earlier conditions applies; we could leave it out and print nothing in the case that N is 4 or 5.
The more compact way to do this is to create a list of values that our number could match; in many programming languages this is called a switch statement. For example:
As a final option, we can use a construction we've seen only briefly before now: a table. The use of tables will be explained more fully in their own chapter, but here we see in brief that we can assign a number of values to one column of a table and then use that table to look up output:
| number | output |
| 11 | "X is eleven!" |
| 12 | "X is twelve!" |
| 13 | "X is thirteen!" |
As we shall see, things other than text can be stored in tables, so we could also use a table as a way to look up objects or even rules to carry out.
178. ★ M. Melmoth's DuelWhile this isn't very interesting as IF, it runs through most of the adaptive-text tricks.
The most straightforward way to alter the response text for something in the standard rules is to select the Index tab, then select Actions, then pick the particular action whose text we'd like to alter. Under action details, there will be icons that look like speech bubbles.
Clicking on the speech bubble will show what the current response text is, and give us an option called "set".
If we click "set", this will automatically paste in the response name that we need to change. We can put this inside a "when play begins" rule in order to make that change take effect from the start of the game, like so:
Room descriptions often make the player character out to be a bit of a savant, able to count whole stacks of items at a glance: "You see 27 paper clips here."
We can adjust this behavior to our liking, though, with the printing a number… activity, as follows:
This general rule can of course be overridden by more specific ones; for instance, if we want to take the opportunity to comment on the viewpoint character's appetite for instruments of correction:
If we want to change individual responses to player action, then the best thing to do is to use the response facility to modify those selections, as shown in the chapter on Responses.
However, suppose what we want is to give the parser a speech impediment that slightly alters all of the responses it issues. For this purpose, we might need to do a bit of text replacement…
Notice that this doesn't affect the printed names of objects in the room description or other kinds of output text -- only those that are issued by the response mechanism.
It would also not work to try to give our parser a nervous personality by simply adding "Um, " to the beginning of each response, because responses are not guaranteed to be full standalone sentences. For example, we could imagine writing
but here is what the room description would say as a result:
We can now change the case of any text produced by a "to say…" phrase. This is often useful when we would like to make use of a standard say phrase in some new context. Say, for instance, that we would like to "[is-are the list…]" in a context that needs the first letter to be capitalized.
We could write a new say phrase, such as "to say is-are the list of (N – a description of objects) in sentence capitalization"; but there is an easier way, and that is to set a text variable to the output of the to say phrase, and then print that text in the case of our choice.
For example:
In this example, we want the names of rooms to be asterisked out if the player wanders around without the benefit of a candle. We can do this by treating the room names as text, then replacing every letter:
Notice that the hyphen in the Absurdly Long-Named Room does not get replaced. We could replace even that, if we liked, with
which would catch every character that is not a space.
438. ★ CurareThe actual number chosen in this definition is pretty much irrelevant: the main thing is that we want to establish relative values. The lower the "last use" number of an item, the older that item should be understood to be, as we see here:
This phrase will select, from the collection of objects passed to it, the one that has been mentioned least recently. This means that if we consult it repeatedly about the same collection, it will begin to cycle predictably; but if new items are added to the collection, it will mention these first before returning to the previous cycle. Now we can use this:
We could have said "You stare morosely at [the oldest thing carried by the player]" here, but doing so would not have set the "last use" property correctly, so we would not get the cycling behavior that we're looking for.
Suppose we are writing a game in which the mood of the piece changes, and we would like to have lots of descriptions that vary according to its current state. We might in that case want to create our own "by atmosphere" token, to control text variations, like this:
Since we're operating within the untyped Inform 6, we can make use of the fact that kinds of value are (internally) just constants, enumerated in the same order in which they were originally defined. In other words, "normal" at the I6 level translates to 1, "melancholy" to 2, and "creepy" to 3; so we can return the value of the current atmosphere, and thereby select option 1, 2, or 3:
And that concludes the hard part. Now to test that it works:
Mostly the Standard Rules use verbs adapted to finite forms ("he jumped", "we take the hammer", and so on). But Inform can also produce participles to describe actions that are ongoing: "he is carrying the fedora" or "taking the hammer…"
In this example, we give non-player characters actions to perform and then have Inform dynamically describe what they're doing when the player chooses to look.
We start by establishing the idea that a verb can describe a particular action:
Now we need to give every character some sort of idle activity. By default, we'll have people just be waiting, but allow for that idle activity to change into something more interesting if the player has told them to do something else.
And just to give past participles a test-drive as well, let's make Clark a bit of a drama king:
Verbs can be related to other things by relations. We've seen that it's possible for a verb to "mean" a relationship. But we can also create a relation between verbs and actions. For instance, we can tell Inform that "take", "get", and "acquire" are all valid ways to describe the action of taking, and then allow it to pick a verb randomly to describe whatever action just occurred.
Some of our default actions establish relations between items in the world, and reporting on the relation ("You are now carrying the fedora") can be a valid response alongside reporting on the action itself ("You take the fedora").
To do this, we need to teach Inform explicitly which relations are the results of actions, then check this when reporting on actions:
| related action | relation |
| the taking action | the carrying relation |
| the wearing action | the wearing relation |
| the taking off action | the carrying relation |
The examples Variety and Narrative Register show how verbs can be associated with particular actions. Here, we use the same principle so that we can report to the player what was last done to a particular object, either by the player or by someone else.
To do this, we need to use the idea of stored actions from the Advanced Actions chapter.
Notice that smelling the box does not change the box's description because we haven't gotten around to defining a smell or sniff verb.
251. ★★ Relevant RelationsSuppose that we wanted authors to be able to indicate which relations should or should not be included in room descriptions, and have the system dynamically honor that instruction.
Inform already knows about verbs for describing supporting, containment, carrying, and wearing, so we could write a set of instructions to handle such cases. To do this, we're using the "writing a paragraph about" activity, which is described in the chapter on activities.
The following uses what is, strictly speaking, a piece of internal machinery not really intended for public use: a variable called "prior named object" which keeps track of what noun other words should agree with. It is not safe to use this variable except to clear it: "now the prior named object is nothing". In a few situations, this prevents glitches in adaptive text.
We can if we like then add alternate names for these relations that will be randomly swapped in some of the time. For instance:
One might, hypothetically, imagine going even further than this and simply designating relations as either "important" or "unimportant" -- perhaps changing the relation's designation at runtime. Relations are not themselves allowed to have properties, however.
60. ★★★ BallparkSometimes it is more sensible to describe numbers roughly than in exact terms. For instance, we might want to have our player perceive "many people" rather than "forty-two people" on entering a room. To achieve this, we might write our own "to say" phrase.
Phrases will be explained more thoroughly in a later chapter, but as we have already seen in the examples, we can make a "To say…" phrase that will allow us to create our own text substitutions. In this case, we are going to replace the specific number with a vaguer one chosen from a chart, so:
| threshold | approximation |
| 1 | "no" |
| 2 | "one" |
| 3 | "a couple of" |
| 6 | "a few" |
| 11 | "some" |
| 21 | "many" |
| 1000 | "lots and lots of" |
The idea here is that we will work our way through the table until we hit a line where the threshold number is higher than the number we want to express, and then print that output: so if we have less than one item, we'll print "no"; if we have more than none but less than two, we'll print "one"; if we have less than three, we'll print "a couple of"; if we have three, four, or five (but not six), we'll print "a few."
There is only so much we can cram into a text property, so being able to swap in properties is useful but limited. Fortunately, we can also, if we want, create new phrases for how to say things in brackets:
Now to provide some meaning to these bracketed forms. We'll start with the easy one:
This is a "to say" phrase; we will learn more about phrases in a later chapter, but for now it may be enough to observe that whatever we write after "to say…" becomes a valid substitution in bracketed speech. In this particular case there is no advantage to using the boast token rather than spelling the text out in the quotation, but we might in theory add further instructions to randomize the output, for instance.
To say phrases can be more complex, as well, since we can have them incorporate extra information:
Here where we have (speaker – a person), we are leaving a slot which we can later fill in, madlibs-like, with any person we like. That is why we can write "insult for the noun": we are summoning the To say phrase and telling it to fill in the identity of the unknown speaker with the noun.
This differs from "insult of the noun" in the previous example; in that case, each person had his own insult property, and were merely printing that property out. Here we are actually telling Inform to calculate anew what the insult should be, and giving it some instructions about how to do that.
Our instructions can also get arbitrarily complex:
So the effects we can get with text substitutions are quite flexible. We could even, if we wanted, fill in the substitutions by random choice, or by selecting items from a long list or table, should we have so bellicose a set of characters that they cannot make do with one or two insulting remarks apiece.
248. ★★★ Narrative RegisterAs we saw in "Variety", we can associate verbs with particular actions and call them up as needed. If we do that, though, we can also store additional information about those verbs and use that information to select the ideal verb to use in a particular situation.
In this example, we create a table of verbs and their meanings, together with some connotative information. Each time we report an action, we then score all the available verbs to decide which is the most suitable to use at the moment. This allows us to change the narrator's diction change mid-game and have the action descriptions change as well.
Moreover, because we're using adaptive verbs, these responses will automatically inflect properly even if we change the story tense and viewpoint.
| word | meaning | connotations | relevance ( a number ) |
| the verb take | the taking action | { } | |
| the verb acquire | the taking action | { pompous } | |
| the verb get | the taking action | { } | |
| the verb gain | the taking action | { } | |
| the verb obtain | the taking action | { pompous } | |
| the verb pick up | the taking action | { } | |
| the verb bag | the taking action | { slangy } | |
| the verb score | the taking action | { slangy, upbeat } | |
| the verb procure | the taking action | { archaic } | |
| the verb grab | the taking action | { slangy } | |
| the verb snag | the taking action | { slangy } | |
| the verb snatch | the taking action | { slangy } | |
| the verb collect | the taking action | { } | |
| the verb discard | the dropping action | { pompous } | |
| the verb drop | the dropping action | { } | |
| the verb put down | the dropping action | { } | |
| the verb toss aside | the dropping action | { } | |
| the verb ditch | the dropping action | { slangy } | |
| the verb throw away | the dropping action | { } | |
| the verb dispose of | the dropping action | { } | |
| the verb set down | the dropping action | { } | |
| the verb abandon | the dropping action | { downbeat } | |
| the verb dump | the dropping action | { downbeat } | |
| the verb abjure | the dropping action | { archaic } | |
| the verb foresake | the dropping action | { archaic } | |
| the verb jettison | the dropping action | { pompous } | |
| the verb dispense with | the dropping action | { pompous } |
Our example is slightly complicated by the fact that "man" is a name already known to Inform, so we can't re-use it as a kind of value. This is possible to work around, though:
Now we borrow from the Activities chapter to look at the exact wording of the player's command:
Making the printed text adapt to circumstances only makes half of the conversation graceful: the other half is to allow the player's commands to have a similar freedom. The things the player can refer to should always respond to the names which would seem natural to the player. Inform provides a variety of techniques for understanding words always, or only under certain conditions; and, if need be, we can also get direct access to what the player has typed in order to examine it with regular expressions. (This last resort is rarely necessary.)
First Name Basis ★ shows how to assign names to things or to kinds of thing – if, for instance, we want the player to be able to refer to any man as "man" or "gentleman":
We may also sometimes want to give names that are specifically plural, as in
or
Vouvray ★★ demonstrates.
A common challenge arises when two objects have names that overlap or are related, and we wish Inform to choose sensibly between them: for instance, a cigarette vs. a cigarette case. If a word should apply to something only as part of a phrase (e.g., "cigarette" alone should never refer to the cigarette case) we can manage the situation as follows:
Because "cigarette" here appears only as part of the phrase "cigarette case", it will be understood only in that context; the conflict with the bare cigarette will not arise.
As a variant, we may want one object only to take precedence over another in naming. If we wanted the player to be allowed to refer casually to the cigarette case as "cigarette" when (and only when) the cigarette itself is not in view, we could add
Tricks which consider the visibility of other objects can be bad for performance if used widely; but for adding finesse to the treatment of a few items, they work very well.
(There may still arise cases where the player uses a name which can legitimately refer to two different things in view. To deal with this situation, we may want the Does the player mean… rules, explained in the chapter on Understanding; and to change the way the story asks for clarification, see the two activities Asking which do you mean and Clarifying the parser's choice of something.)
Names of things which contain prepositions can also be tricky because Inform misreads the sentences creating them: Laura ★★ shows how some awkward cases can be safely overcome.
A more difficult case is to ensure that if we change the description or nature of something in play, then the names we understand for it adapt, too. "Understand… when…" can be all that's needed:
Or, similarly, if we want some combination of categories and characteristics to be recognized:
"The item described" here refers to the thing being named. "…when" can even be useful in defining new commands, and Quiz Show ★ demonstrates how to ask open-ended questions that the player can answer only on the subsequent turn.
Properties can also be matched without fuss:
This allows EXAMINE AQUAMARINE WALLPAPER if, but only if, it happens to be aquamarine at the moment. Relationships can also be matched automatically:
which recognises BOX OF CRAYONS until they are removed, when it reverts to plain BOX only.
Greater difficulty arises if, using some variable or property or table to mark that a bottle contains wine, we print messages calling it "bottle of wine". We are then honour-bound to understand commands like TAKE BOTTLE OF WINE in return, not to insist on TAKE BOTTLE. Almost all "simulation" IF runs in to issues like this, and there is no general solution because simulations are so varied.
A converse challenge arises when we want to avoid understanding the player's references to an object under some or all circumstances. This is relatively uncommon, but does sometimes occur. For this situation, Inform provides the "privately-named" property, as in
Here "privately-named" tells Inform not to understand the object's source name automatically. It is then up to us to create any understand lines we want to refer to the object, as in
Of course, if we need an object that the player is never allowed to refer to at all, we can just make this privately-named and then not provide any understand lines at all.
A final source of difficulty is that by default Inform truncates words to nine letters before attempting to identify them. This is no problem in most circumstances and is likely to go unnoticed -- until we have two very long words whose names are nearly identical, such as "north-northwest exit" and "north-northeast exit". (To make matters worse, a punctuation mark such as a hyphen counts as two letters on its own.)
When we are compiling for Glulx, the limit is easily changed with a single line, setting the constant called DICT_WORD_SIZE. For instance, if we wanted to raise the limit to 15, we would write
When compiling for the Z-machine, the solution is harder. North by Northwest ★★ shows how to use the reading a command activity to pre-process very long names, rendering them accessible to the parser again.
Inform also allows the player to refer to the most recently seen objects and people as IT, HIM, HER, and so on. It sets these pronouns by default, but there are times when we wish to override the way it does that. Pot of Petunias ★ shows off a way to make Inform recognize an object as IT when it would not otherwise have done so.
(See Using the Player's Input for an example (Mr. Burns' Repast) in which a fish can be called by any arbitrary word as long as it ends in the letters -fish.)
Liquids for a resolution of this bottle-of-wine issue.
Memory and Knowledge for a way to refer to characters whom the player knows about but who aren't currently in the room.
Clarification and Correction for ways to improve guesses about what the player means.
Alternatives To Standard Parsing for several esoteric variations on the default behavior, such as accepting adverbs anywhere in the command, and scanning the player's input for keywords.
Sometimes we create objects that we want the player to be able to call by different names: a television that should also answer to "tv" and "telly", for instance, or a refrigerator the player might also call "fridge". In this case, we can use instructions like
to add extra names to the object we've defined.
(This description is for local color; we will learn more about devices, and conditions like "if switched on", later in this chapter.)
By default, Inform does not understand the names of an object's kind as referring to that object, unless the object has no other name of its own. We can change this, if we like, by defining names that should be applied to everything of a given kind:
Inform's naming abilities go considerably further, in fact: we can also instruct it to understand words only under certain circumstances, or only when they appear with other words. Fuller details may be found in the chapter on Understanding.
323. ★ Quiz ShowBecause of the "…when" part of this line, random text is only treated as an answer when a question is being asked.
This next rule allows a player to do something other than answer the question, but then makes him wait for another question before answering.
| State | Topic | Comment |
| "Florida" | "1845" | "March 3rd" |
| "Delaware" | "1787" | "December 7th" |
| "Hawaii" | "1960" | "July 4th" |
Note that the situation will become a little more complicated if we have two or more identical topics in our trivia list; in that case, we would need to loop through the Table of Dates of Statehood explicitly, and only mark the player wrong if none of the lines were found to match. (See the chapter on Tables for many more ways to manipulate table behavior.)
325. ★ Pot of PetuniasSuppose we have an object that makes a dramatic entrance on the scene, like so:
If we leave out the "set pronouns…" line here, we'll wind up with the following very unsatisfactory end to our test transcript:
Occasionally it is useful to give something a printed name because we want to call it something extremely long-winded; give one thing a name that is the subset of the name of something else; or use words such as "with" or "and" that are likely to confuse Inform into thinking that the object name ends before it actually does.
Often it is enough to preface these ambiguously-titled things with "a thing called…" or "a supporter called…" or the like, as here:
prevents Inform from trying to read "Hot and Sour Soup" as two separate rooms, while
creates two objects instead of the one orange ticket that would result if the second sentence were merely "The player carries an orange."
Really long names can be a bit cumbersome. For example:
So we might instead give the photograph a printed name:
Now we've gotten around any awkwardness with printing the name -- but we also need to understand when the player refers to the photograph. When we define the names of objects under normal circumstances, Inform takes care of this automatically, but if we have especially set the printed name, we must also specially define the appropriate terms for the player to use. For this we need "understand", which will be explained in much more depth in a later chapter:
That's probably as far as we really need to go, and if you are satisfied with this behavior, there is no need to read on.
One possible objection to this solution is that Inform will accept some nonsensical formulations as applying to the photograph: for instance, it will allow >EXAMINE PHOTOGRAPH OF, >X BLONDE PHOTOGRAPH WOMAN INCRIMINATING, or even >X OF …though in the case there were two items with "of" names, the game would disambiguate with a question such as "Which do you mean, the incriminating photograph of a woman with blonde hair or the essence of wormwood?"
Traditionally, Inform has tended to be fairly flexible about word order, preferring to err in the direction of leniency. On the other hand, there are times when we need more exacting rules in order to distinguish otherwise similar cases.
Two features allow us to specify more exactly if we so desire. The first is that, if we specify a whole phrase as the name of something, all the words in that phrase are required, in the order given. Thus "Understand "blonde hair" as the photograph" would require that both "blonde" and "hair" be present, and would not recognize >X BLONDE, >X HAIR BLONDE, or >X HAIR.
Second, we can create tokens, such as "Understand "blonde hair" or "hair" as "[hair]", and then use these tokens in match phrases. This saves a good deal of time when we want to specify a number of different but fussy alternatives. So, for instance, here is a drawing that would not respond to >X OF, or >X BROWN EYES, but would respond to >X DRAWING OF MAN WITH BROWN EYES, >X MAN WITH BROWN EYES, and so on:
Further refinements are possible: the "privately-named" attribute tells Inform not to try to understand the source name of an object at all, so if we write
…the player will not be able to refer to it as "purple" or "rabbit" or "purple rabbit".
There are also ways to make names to refer to entire kinds of objects (so "dude" will refer to any man in the game); to specify names that only refer to objects in the plural (so GET PICTURES will pick up several pictures together); to reflect an object's properties (so "red apple" works only as long as the apple is in fact red); or even to refer to the object's relationships to other objects (so "bottle of wine" works only when wine is indeed in the bottle). All these refinements are discussed in the chapter on Understanding.
43. ★★ VouvrayThe Understanding chapter lays out ways to change how the player can refer to objects, but we may not want to wait that long for some of the basic features. Here, for instance, is how to add synonyms that the player can use to refer to an entire kind of object:
Suppose we wanted to add intermediate compass directions such as north-northwest to our game. Because of the limitations of the index map, we won't be able to view these connections on the world map, but we can certainly create them, and use them in route-finding, just like other directions.
Here's how we'd set up such a thing:
A complication arises because we reach the 9-character limit: Inform truncates the names of objects to nine characters before trying to understand them. To make matters worse, the hyphen (and other punctuation marks) count as two letters. So both north-northwest and north-northeast will get truncated to "north-no", and be indistinguishable when the player types them.
When we are compiling for Glulx, the limit is easily changed with a single line, setting the constant called DICT_WORD_SIZE. For instance, if we wanted to raise the limit to 15, we would simply write "Use DICT_WORD_SIZE of 15."
If we're compiling to the Z-machine, however, we'll have to resort to some manipulation of the player's command. The general solution is that when the player's name for an object is going to have to be longer than we can correctly read, we can substitute an unambiguous abbreviation for the thing the player typed. In this case, it will be simplest and most efficient always to condense the player's direction names to single letters, thus:
For more on the use of text, see the Advanced Text chapter.
In practice, this is going to be overkill for almost all games: most players already find eight compass directions plus up and down to be enough (or more than enough) to keep track of. But the option exists, in case there is a compelling reason to use it.
(Note also that we are allowed to use multi-word direction names, so we could have called the directions "north by northwest", "north by northeast", and so on. This example deliberately takes the hard way in order to show how to resolve the nine-character problem.)
We may sometimes want to capture specific words the player has used and then feature that text elsewhere in the story.
Terracottissima Maxima ★★★ demonstrates using text to describe objects; Mr. Burns' Repast ★★ lets the player refer to a fish by any of a number of names, and changes the way the fish is described as a result.
More specialized effects are also possible: Xot ★★★ shows how to collect the player's erroneous input and store the command line to be printed back later. Igpay Atinlay ★ shows how to parrot the player's command back in pig Latin form.
Animals for a dog which the player can re-name.
Traits Determined By the Player for a way to let the player name the player character.
For the sake of argument, suppose we want to parrot back all the player's commands in pig Latin:
Suppose we have an unhappily mutated fish that the player can refer to by any of a number of species names, or any word followed by -fish. We want to reject these commands, but preserve a memory of what the player last tried to call the thing:
Inform can also understand text properties:
This may not seem very much different from having the pattern be a kind of value -- except that texts can, of course, hold almost anything. Further exploration of these possibilities may be found in the chapter on Advanced Text.
381. ★★★ XotIn Hitchhiker's Guide to the Galaxy, any erroneous command the player types can return to haunt him later in the game. We could do the same, if we liked, by storing the player's command whenever we print a parser error.
The printing of a room description is a more delicate business than it might initially seem to be: Inform has to consider all the objects that the player might have brought into the room or dropped there, and all the objects on visible supporters, and decide how to group and list them.
All of this behavior is handled by the looking command, so we find the relevant rules in the carry out looking rulebook. To go through the elements step by step:
Looking begins by printing the name and description of the room we're in. We can introduce variations into room names and descriptions by changing their printed name and description properties, as in
If we need more drastic effects, we can turn off or change either of these features by altering the rules in the carry out looking rulebook. For instance, to remove the name of the location entirely from room descriptions, we would write
(A word of warning: there is one other context in which the story prints a room name — when restoring a save or undoing a move. To omit the room title here too, add
Ant-Sensitive Sunglasses ★ demonstrates how to use activities to make more flexible room description text.
Next, the story determines what items are visible to the player and need to be described. These never include the player himself, or scenery, but other things in the environment will be made "marked for listing". This is also the stage at which Inform chooses the order in which items will be listed.
We are allowed to meddle by changing the priorities of objects, in case we want some things to be described to the player first or last in the room description; Priority Lab ★ goes into detail about how. We can also force things to be left out entirely: Low Light ★ handles the case of an object that can only be seen when an extra lamp is switched on, even though the room is not otherwise considered dark. Copper River ★★★ implements the idea of "interesting" and "dull" objects: the story determines which items are currently important to the puzzles or narrative and mentions those in the room description, while suppressing everything else.
Then Inform carries out the writing a paragraph about… activity with anything that provides one; anything it prints the name of, it tags "mentioned". Thus
will count Wickham and everyone he looks at as all having been mentioned, and will not refer to them again through the rest of the room description. More complicated uses of writing a paragraph abound. A developed system for handling supporters that don't list contents appears in The Eye of the Idol ★★.
Inform then prints the initial appearances of objects that are marked for listing but not already mentioned; and then it performs the listing nondescript items activity, collating the remaining objects into a paragraph like
We can pre-empt items from appearing in this paragraph or change their listing by intervening with a Before listing nondescript items… rule, as in
If we wanted the watch always to be listed this way, it would be better to give it an initial appearance, but for conditional cases, the listing nondescript items activity is a good place to intervene. For instance, Rip ★ uses this activity to incorporate changeable or portable items into the main description text for a room when (and only when) that is appropriate.
The listing nondescript items activity also allows us to replace the "You can see…" tag with something else more fitting, if for instance we are in a dimly lit room.
When the story compiles the list of nondescript items, it adds tags such as "(open)" or "(empty)" or "(on which is a fish tank)" to the names of containers and supporters. We can suppress or change the "(empty)" tag with the printing room description details of activity, as in
And we can suppress the "(open)" and "(on which is…)" sorts of tags with the "omit the contents in listing" phrase, as in
Finally, the looking command lists visible non-scenery items that sit on scenery supporters, as in
These paragraphs can be manipulated with the printing the locale description activity and the printing a locale paragraph about activity.
Another common thing we may want to do is change the description of a room depending on whether we've been there before (as in Slightly Wrong ★★) or on how often we've visited (as in Infiltration ★). Night Sky ★, meanwhile, changes the description of a room when we've examined another object, so that the player's awareness of his environment is affected by other things the character knows.
Looking for ways to change the default length of room descriptions.
Sometimes a nice effect is to change the way things are described depending on the information the player has gained in the course of play. We could for instance write this:
On the other hand, beware that this would not work as desired:
The reason is that our Instead rule has pre-empted normal listening, so Inform considers that we have never successfully heard the message. The moral here is that "if we have…" is useful for tracking events that otherwise proceeded completely normally (picking up ordinary objects, examining things); if we have used instead to make some change, we will have to use a different approach to record that the event did occur as scheduled.
152. ★ InfiltrationSuppose we have a location that makes the player uncomfortable, and we want its description to change slightly each time he goes there, to reflect his increasing unease. We also want the door to that room to show whether he is going there for the first time, or whether this is a repeat visit.
We start with an ordinary room:
Now the door, which will change from saying "leads inside…" to "leads back inside…" when this becomes appropriate:
Here we haven't used any conditions that we didn't know about in previous sections: the portal line only reflects whether the Zone has been visited never or visited once. But the Secure Zone itself makes use of the number of times visited:
And finally, to be sure that the player does see our fancy changing descriptions:
Notice that the description of the Secure Zone changes from visit to visit, but that looking repeatedly during a single visit changes nothing.
334. ★ Ant-Sensitive SunglassesSuppose we want to create an object -- or maybe even a series of objects -- that warp the player's perception of every room description and object around him.
We've already seen some ways to create variations in text. For instance, we could make a room description with if substitutions in it, like so:
That works fine if we have one or two variations we want to add; it's not so good if we're going to have several items that work like the sunglasses, or if we want the sunglasses to override the description of every room in the house.
A slightly more flexible method is to use a substitution that calls out to a say phrase, like this:
But again this doesn't handle the case of overriding multiple rooms at once very well.
When we reach a point where we need a given piece of text to be very flexible depending on the world model, it's time to use an activity.
Activities offer several advantages. One, we can create an activity like this:
and then write a rule that applies to multiple rooms at once, like:
Inform's usual rule-ranking also means that more-specific rules will override less-specific ones, so we could add
and have that rule override the behavior of the activity just in the kitchen. Meanwhile, our base room descriptions remain straightforward and uncluttered by if-statements.
Several other examples will show how to hook activities into existing actions: Crusoe goes into detail about how how to make the descriptions of things more variable, and Aftershock demonstrates activities for describing the behavior of switchable devices.
Here, we preview all of those methods, just to get a sense of how they work and why they might be useful in controlling a game. Subsequent chapters go into more detail about the syntax of creating activities and the list of activities that are already defined by Inform.
To add a new activity to an existing Inform rule, we need to do three things:
1) Define our new activity.
2) Give a basic rule that says what is supposed to happen when that activity occurs, as in "Rule for…"
3) Replace the existing rule in Inform's rulebooks with a new one that calls on our activity.
Here we do this with examining:
Now, by default, we want to print the description property; we just want the option to write some extra rules overriding that property. So we tell Inform that our most basic rule for printing the description of something is just to give that description text:
Next, we need the standard examining rule to look at our printing-the-description activity:
Now we do the same thing to room descriptions.
Our replacement rule this time around is a little bit trickier just because the rule that we're replacing is a complicated one: describing a room already checks to see whether there's light to see by, whether the player has turned off room descriptions when he enters a room for the second time, and whether the player character is (say) inside a closed box he can't see out of.
But all of those details are re-copied from the standard rules, and the important thing is that, at the end, we again carry out our activity.
There are times when, for greater elegance of prose, we'd like to mention an object in the main body text of a room. For instance:
As we've already seen, that's no problem if Rip is scenery. He'll stay there motionless.
But what if something in the game allows Rip to wake up? Or what if we want to use the same technique on a portable object that the player should be allowed to take? Clearly in that case it's not appropriate to make the mentioned thing be scenery, and at the same time, we need to keep Inform from adding a superfluous
to the end of our description.
Here is how:
When it comes time to start manipulating the priorities of items, it is useful to be able to check the table for debugging purposes; the problem is that printing the names of the objects can itself affect the way the room description is generated, foiling our debugging efforts.
What follows is a rule to help with debugging safely, and a sample of how priorities work:
Now, let's look at some items put in a specific order. Things with low priority numbers list towards the beginning; things with high priority numbers list towards the end. (It helps to think of it as though we were making a numbered list of the paragraphs to appear in the description.) Anything numbered 0 doesn't appear at all, and the default priority of an object is 1.
An important cautionary note: priorities are only honored if the objects are going to get their own paragraphs (with "writing a paragraph about…" or because they have initial appearances). Priorities do not affect the order in which items appear in the final "You can see…" list, except that items with priority 0 or lower are omitted. (If we want to order the items in that list, we may want to resort to the Complex Listing extension by Emily Short.)
There are further refinements available to us: for instance, we could make some things that are only visible if the player is raised above ground level.
It may also be useful to know about the "parameter-object", which refers to the thing whose contents we are currently describing: the standard rules consider how to describe the contents of the location and then also check the contents of any supporter or container the player may be inside, so in the first case "parameter-object" would be the location, and then in the second the supporter in question.
In practice this is rarely useful, but should we need to change priorities in the case of both player and object being inside a particular container, we might make use of it, for instance:
The other thing to note is that by default that final collection of generic objects ("You can also see…") appears at the end, regardless of the priority of everything else. If we really wanted to, though, we could force something to appear even after that paragraph, by adding a new listing rule to the locale description rules:
In order for the priorities we just set to be interesting, let's give out some initial appearances and writing a paragraph rules:
This procedure also means (as you can test by experiment) that after the late edition has been picked up and dropped again, it lists in no special order in the "you can see…" paragraph (since initial appearances only print when the object has not yet been moved).
Suppose we want a different treatment of lighting than the usual: the room isn't totally dark, but there's something we can't see unless we turn on a bright light.
First we make our environment and its light:
Now we make a shadow so that the player can only refer to it if the shadow is in inventory or the light is on:
And finally a couple of extra touches to make it clear why we're able to interact with the shadow when it's in inventory, even if the light is low:
To handle the appearance of the object, we want to set its locale priority to 0: that will prevent it being named in room descriptions.
A fairly common effect in interactive fiction is a room which is described differently on the first visit than on subsequent visits. We can produce this effect as follows:
Note the "[if unvisited]…" in the description of the Slightly Wrong Chamber. A room is considered to be "unvisited" until after the player has seen its description for the first time.
The bracketed text creates a special rule for printing; we will learn more about these in the sections on text with variations and text with substitutions.
Some further fine print: we might write our condition as "if unvisited", "if the location is unvisited", or "if the Chamber is unvisited" -- all of these constructions would be acceptable, but in the absence of more specifics, the condition is understood to apply to the object whose description it is.
357. ★★ The Eye of the IdolWe start by defining relations that let us know where items "belong", with the understanding that if something is where it belongs, it will be described in the main room description and therefore should not be separately listed. Thus:
We can't make relations relate various objects to various objects, and rooms are not things, so two separate cases are necessary. An alternative approach would be to say "A thing has an object called the initial placement", which would allow a thing to have an initial placement that was a room, a supporter, or a container; an advantage of using relations, though, is that that way we can if we like specify multiple placements for the same object, so that, e.g., a sparkling diamond can be described in the main description paragraph as "half-buried in dust" in the beginning of the game, and then at the end as "in the eye of the idol" at the end.
Now we define, based on these relations, an "in-place" adjective, which will identify whether something is in a location which will specially describe it:
With that done, removing these items automatically from the room description is actually pretty easy:
One tricky case remains: when something is placed on a supporter that is scenery, it can be mentioned even if we have marked that object "not marked for listing". What matters here is not whether the object itself is marked for listing but whether the supporter has been "mentioned". (A fuller description of how room descriptions are assembled is available in the Looking section of the Commands chapter in the Recipe Book.) So let's also add a feature whereby we can easily suppress the descriptions of these supporters when appropriate:
A quiet supporter is one that is never mentioned itself and which only mentions its contents if they are out of place. This allows for maximum flexibility in incorporating it into the body of room descriptions.
Notice that we can still override this with writing a paragraph rules about specific supporters in our game, if we decide that we want something a little different in some cases.
Now, an example to test this out:
We could have done all this with text conditions in the main room description, but it becomes difficult to read when there are too many conditions operating in the same text property, so we break it out into a clearer set of conditions.
In a very dense environment, we might want to offer the player room descriptions in which only the currently-interesting items are mentioned, while other objects are suppressed even if they are present. In effect, this takes the idea of scenery and makes it more flexible: different things might become background objects or foreground objects at different times during play.
There are a wide range of possible reasons to do this -- to shift the narrative emphasis, to change the mood of the game by highlighting different parts of the environment, to show the game from the perspective of different viewpoint characters -- but in the following example, our goal is to show the player only the objects that are currently useful for puzzles.
To do this, we need some notion of what puzzles are currently available and unsolved, so we make an "unsolved" adjective; we also need to know which things solve the puzzle, so we create a "resolving" relation, to indicate which objects resolve which problems.
Given that information, we can create rules about which objects in the game world are currently interesting, which are currently dull, and describe accordingly:
A work of IF contains many spectacles and activities, and these must not all present themselves at once, or the player will be overwhelmed. One way to spread them out is in time, by having them available only as a plot develops, but another is to spread them out literally in space. The player has to walk between the Library and the Swimming Pool, and thus bookish and athletic tasks are not both presenting themselves at once. There have been valiant "one-room" IFs, and it forms a respectable sub-genre of the art, but most works of any size need a map.
Inform, following IF conventions, divides the world up into locations called "rooms", connected together by so-called "map connections" along compass bearings. Thus:
The example Port Royal ★ develops a medium-sized map from such sentences. This develops in Port Royal 2 ★ to include connections which bend around, allowing the rooms not to lie on an imaginary square grid.
Because it is useful to group rooms together under names describing whole areas, Inform also allows rooms to be placed in "regions". Thus:
Port Royal 3 ★ demonstrates this further. A&E ★★ shows how regions can be used to write simple rules which regulate access to and from whole areas of the map.
Many old-school IF puzzles involve journeys through the map which are confused, randomised or otherwise frustrated: see Bee Chambers ★ for a typical maze, Zork II ★ for a randomised connection, Prisoner's Dilemma ★★ for a change in the map occurring during play. A completely random map takes us away from traditional IF and more towards a different sort of old-school game, the computerised role-playing game with its endless quests through dungeons with randomly generated treasures and monsters. This style of map – building itself one step at a time, as the player explores – can sometimes be useful to provide an illusion of infinite expanse: see All Roads Lead To Mars ★.
While the standard compass directions are conventional in IF, there are times when we may want to replace them without other forms of directional relationship. Indirection ★ renames the compass directions to correspond to primary colors, as in Mayan thinking. The World of Charles S. Roberts ★★ substitutes new ones, instead, introducing a hex-grid map in place of the usual one.
Going, Pushing Things in Directions for ways to add more relative directions, such as context-sensitive understanding of OUT and IN.
Room Descriptions for ways to modify the room description printed.
Ships, Trains and Elevators for rooms which move around in the map and for directions aboard a ship.
Unless we arrange otherwise, this will be the first room in the game because it is the first we have defined.
For subsequent rooms, we do not have to say explicitly that they are rooms, as long as they are connected to a room on the map. For instance, this will automatically make Thames Street End a room:
If we have some concern that the room name will be confused with an existing name, we can be more explicit about it using "called":
And now we get "inside", which generates a space treated as its own area on the map.
And if we like we can declare a number of rooms for which we will come back and write the descriptions later. There is no obligation for the description to occur at the first definition of the room.
For efficiency, we can also write multiple sets of connections at once:
Clicking Go will translate this description into a sketchy but working simulation of Port Royal, in which we can type movement commands like EAST or SOUTH to explore the streets. Looking at the World tab of the Index, we can also see a schematic map of the simulation as it currently stands. Like the rest of the Index, this is provided entirely for the author's benefit, and is not visible to the player. (Though if we do decide that we want players to have access to a printed map while they play, Inform can help: we will return to the layout of Port Royal in the chapter on Publishing.)
The following Test command allows us to type TEST ME and explore the map we just devised:
If we check out a map of historic Port Royal, we find that Thames Street End bends around the northwest tip of the peninsula and becomes the (very) roughly north/south Fisher's Row. We can't put Fisher's Row south of Thames Street End, though, because Lime Street is already going that way. So instead, let's have a map connection that bends around from west to north:
Now continuing west along Thames Street, or north along Fisher's Row, will bring us around the corner in question. Asymmetric map connections should be used carefully. They're good for representing the layout of the real world, which tends not to be laid out on a convenient square matrix, but if exits are not described clearly they can be disorienting for the player. So let's be sure to make things clear:
Meanwhile, suppose Fort James is in a prominent position, raised a bit from its surroundings; maybe the player should be able to go down from there, as well as south, to get to Thames Street End.
But we don't want the upward direction to work:
We should go ahead and do all our room definitions first…
Now, if we like, we can create regions to distinguish the coast from the portions of town that aren't on the water:
There's no rule that regions must be contiguous, so we could if we like make a region consisting just of the two forts:
And we might make the Feathers Tavern part of the Inland area, but within its own subcategory:
Now the index map will be colored to reflect our regions, and later in the game development we would be able to make rules that affect just one region at a time.
78. ★ All Roads Lead to MarsSuppose we want to allow the player to wander freely in any direction, but ourselves maintain control over the order in which he encounters the rooms. This sort of effect emphasizes the order of the story-telling over any kind of rigorous simulation of space; on multiple play-throughs, the player might not find all the same rooms in the same locations.
If we wanted still to be able to find routes between places, we could define a relationship of connection between rooms, which we would add to as we went along.
125. ★ Bee ChambersMazes are a traditional element of interactive fiction, often consisting of apparently identical rooms with exits that do not work reciprocally and which cause confusion.
The methods of mapping mazes are now fairly well understood and mazes themselves tend to be regarded as tiresome rather than enjoyable by a large portion of the playing audience. However, if we did want to ignore the common wisdom and create a maze, randomly generated at the start of play, here would be one way to go about it:
All we need to do is select the player's destination for him at random:
To avoid infringing the original game too much, let's try a somewhat different setting:
And the following means that the test runs consistently even though the numbers are theoretically random. To make them truly random, remove this line.
Or if we want to add the refinement that the Carousel Room can be switched off:
And then
In Mayan culture, colours seem to have been used as names for the primary directions: for instance, "red" implies east as the colour of sunrise. So the following might be a stylish touch for a game in which the player has to get inside the Mayan world-view:
We could also use a colour as a verb:
And now a few extra rooms to try it out in:
We can change the directions in the map in mid-game, though in practice this is rarely necessary. But suppose we do not want a door or any sign of a door to exist before the player takes some action, in this case pressing a button:
Our instructions about pushing the button will be further explained in the chapter on Actions, but the thing to note here is that we can "change (whatever) exit" in order to set or re-set map directions. Notice that we have to set both directions explicitly: changing the east exit of the Waiting Room does not automatically also change the west exit of Amid the Cheering Throng.
This allows greater flexibility in our games but does require an extra line or so of work.
41. ★★ The World of Charles S. RobertsWargaming is an ancient pursuit, but its modern form began as a professional training exercise in 19th-century Prussian staff colleges; since at least as early as H. G. Wells's "Little Wars" (1913) it has been a hobby of "boys from twelve years of age to one hundred and fifty and for that more intelligent sort of girl who likes boys' games and books." The free-form tabletop game used miniature figures and tape-measured movements, and remains the dominant form today. But in the mid-20th century, map grids on printed sheets gave the hobby a sudden new lease of life. They were easier to set up, more interesting to look at, cheaper to sell by mail-order. 1970s sales figures for "Strategy and Tactics", the leading US subscription-based wargame distributor, were very similar to those of Infocom's IF games in the 1980s. And like classical IF, the grid-based wargame parceled up a continuous world into locations.
Grids were initially square, as on a chessboard, but square cells have several disadvantages. Four directions of movement (N, E, S, W) is too few, yet allowing movement in the diagonal directions means allowing tanks to travel about 1.4 times faster northeast than they do north. Square grids also only conform cleanly to man-made landscape features such as buildings in one orientation, and they never fit hills well. (A compromise measure to fix this, cutting the squares into octagons to leave smaller diamond squares at corner intersections, has never caught on.)

But following Charles S. Roberts's American Civil War designs for Avalon Hill of 1958-61 (notably "Chancellorsville" and the second edition of "Gettysburg"), a hexagonal grid became the new standard. Each hexagon is the same distance from the centre of all six of its neighbours, which are at equal angular spacings; and clumps of hexagons fit the shape of lakes, contoured hills, and so forth, much more naturally than clumps of squares do. Hexes also have a certain mystique – an air of "I don't belong in the children's department".
But hexes are tricky for IF, not least because English lacks words for "the direction 60 degrees around from front". Our cognitive view of the world tends to be square, perhaps because our two eyes both face front, in a direction at right angles to the plane of our arms, legs, pelvis and eyes. We reach out sideways at right angles to our walking. Even early hex-grid wargames called the cells "squares", though "hexes" eventually caught on. Still and all:
Now to forbid the use of the compass directions:
A slight nuisance is that, with things as they are above, typing BACKWARD produces the response "Which do you mean, backward, backward left or backward right?" To avoid that silly question, we write:
And now a clump of 37 hexes, in six columns of six or seven rooms each. There are many ingenious ways we could put this map together automatically, but instead we will take a deep breath and write:
And now we have a hexagonally-gridded world. Route-finding will work; prepositional forms like "to be mapped backward left of" exist, just as they should; and in general these directions are just as good as the square ones. (The only thing which doesn't look good is the Index map, where Inform is just unable to draw a picture because it assumes a square grid. But that has no effect on play.)
The landscape is much easier to navigate with a little diagram:
And finally:
Rules about going to regions make it easy to exclude the player from a large portion of the map, even if there are many connecting paths to the region. For instance, in this story it would be annoying to have to write a rule about all four exits by which the player could reach the film set area:
Inform's division of geography into "rooms" is a good compromise for most purposes. The rooms are cut off from each other by (imaginary or actual) walls, while all of the interior of a given room is regarded as the same place.
Suppose we want things to happen differently in different corners of the same room? Inform can already do this a little, in that the player can be inside an enterable container or on an enterable supporter. For instance:
If we need to have divided-up areas of the floor itself, the standard approach is to define a small number of named positions. We then need to remember at which of these locations the player (or something else) currently stands.
Further Reasons Why All Poets Are Liars ★ allows the player to be in different parts of a room by standing on a box which can be in different places: thus only the box needs an internal position, not the player, simplifying matters neatly.
Another interesting case is when one room is entirely inside another (such as a hut in a field, or a booth in a large convention hall), so that the exterior of the room should be visible from another location. Starry Void ★★★ gives a simple demonstration of a magician's booth that can be examined from the outside, opened and closed, and entered to reach a new location.
Continuous Spaces and The Outdoors for making the space between rooms continuous.
Combat and Death for the use of position in a room in determining combat maneuvers.
Entering and Exiting, Sitting and Standing for automatically getting up from chairs before going places.
The Human Body for letting the player take different postures on furniture or on the floor.
Furniture for cages, beds, and other kinds of enterable supporters and containers.
We begin with the location and its fittings, and we create a kind of value which names the different internal positions we will allow.
We create an action, "pushing it over to", for pushing a box around on the floor of a single location. (Calling this "pushing it over to" prevents clashes with the existing "pushing it to" action, which is for pushing things from one room to another.) Almost half of the text which defines the action is concerned with the two action variables, but they make the implementation of everything else so much easier that we end up writing less than if we hadn't used them.
Everything which remains simply provides a couple of puzzles to test this arrangement.
Sometimes we may want a room to be visible from the outside in one location, but treated as a separate location when we are inside. The simplest way to do this is to make the exterior form of the object into a door object, and to describe it differently from different vantage points. (Doors in general are described more fully in the Doors section of the Things chapter.)
Here we've arranged for the booth to be described in the initial room description in different ways depending on where the player is when viewing it. We might like to do the same if the player takes a closer look:
And now we put it in place:
…and make sure that the booth-and-door object responds to all the names we have used for it in different places:
A final nice touch, if we're so inclined, is to borrow from the Basic Actions chapter and make the player automatically open the booth door before trying to enter:
For the contrasting case of a space that is nested inside another place and is not its own room -- say a stall at an open-air market, or a rowboat on a lake -- see the example "Tamed".
Suppose we want to blur the boundaries between rooms, in an environment where there are no walls: out of doors, for instance?
The simplest cases involve making something exceptional visible in more than one place. Carnivale ★★ features an exceptionally large landmark seen by day; Eddystone ★★ an exceptionally bright one by night. Waterworld ★ allows a very distant object (the Sun) to be seen throughout many rooms, but never approached. View of Green Hills ★★★ gives the player an explicit command for looking through into an adjacent room.
Three systematic examples then present outdoor landscapes with increasing sophistication. Tiny Garden ★★ gives the multiple rooms of an extended lawn descriptions which automatically adapt to say which directions lead into further lawn area. Rock Garden ★★ provides a relation, "connected with", between rooms, allowing items in one to be seen from the other: an attempt to interact with a visible item in a different area of the garden triggers an implicit going action first. Stately Gardens ★★★ provides a much larger outdoor area, where larger landmarks are visible from further away, and room descriptions are highly adaptive.
In an outdoor environment, the distinction between a one-move journey and a multiple-move journey is also blurred. Hotel Stechelberg ★★ shows a signpost which treats these equally.
Position Within Rooms for making the space within a room continuous.
Windows for another way to see between locations.
Doors, Staircases, and Bridges for still a third way to be told at least what lies adjacent.
Passers-By, Weather and Astronomical Events for more on describing the sky.
It's tempting to handle the player's inability to interact with something with a simple instead rule:
Unfortunately, the rule does not address the case where the object in question is the second noun; so for instance the following example reveals the difficulty:
…where the response here behaves as though the sun is in reach. If we had a fully implemented tying action, the player would (even more disastrously) be allowed to lasso celestial objects.
We could add a second instead rule as well:
Sometimes we want to make a list of something too complicated to express in a say list… phrase. When this happens, we can instead mark all the items we want to mention as "marked for listing".
In this case, we have a lawn area made up of four rooms. We want each room to automatically describe the directions leading to the other parts of the lawn. To do this, we will first determine which directions are relevant and mark those for listing, then list them.
The following phrase goes through all the directions in the compass and marks the ones that are interesting to us at the moment.
The following rule appends a paragraph to every room description. We need not worry about doors (despite the pass in the Bernese Oberland known figuratively as the "Little Door").
With a bit more work, the result might be:
Suppose we want to make an object that (unlike a backdrop) is definitely located in one room, but can be seen from far off. We want to allow the player to interact with it from a distance, but only using those actions that require visibility. Other actions should be denied:
As the descriptions make clear, the ferris wheel should be visible from everywhere in the fair, so we'll borrow a line from the Activities chapter to make that happen:
"Scope" determines what the player can interact with; by writing this rule, we make Inform understand all commands that refer to the ferris wheel when the player is anywhere in the fairground, instead of responding with
as it normally would.
Now, by default, if the player were to type TOUCH FERRIS WHEEL while in another room, he would get the response
This may not be quite what we want, but we can replace this text with our own reaching inside rule:
And because our accessibility rules are considered before the "Instead" phase, we can write the following rule confident that it will apply only when the player is in fact in range to touch the ferris wheel:
Using the compass directions in commands is a little bit finicky because directions are forbidden to figure in any interactions involving touch. (Really, directions are more a concept than an object; this is a compromise situation.) In any case, if we want to write a new command involving these, we need to be sure to specify that the direction is a visible thing. For instance:
will give us
To avoid this mystifying result:
And now that's done, we have a little fun calculating where the beam hits:
All very loosely based on the Eddystone Point lighthouse of Tasmania, built in 1889, and forbiddingly remote even today. George Isaacs, a child growing up in the lighthouse, remembers the plentiful crayfish.
366. ★★ Rock GardenA map of linked rooms works well for modeling enclosed or indoor space, and somewhat less well for modeling large open spaces, where a person should reasonably be able to see things which are much too far away to touch. With some modifications to scoping, though, we can create an environment where objects in nearby rooms are described and viewable, and where the player will automatically move towards distant items before interacting with them physically.
Suppose a game in which the player is wandering an open landscape with long vistas, allowing him to LOOK in some direction, or even look at an adjacent location.
In rules about action handling, "noun" refers to the first object that the player has mentioned in his command, so if the player typed >LOOK WEST, "let the viewed item be the room noun from the location" would be processed as "let the viewed item be the room west from the location", and so on.
We can at need override the default behavior, if it is not going to be appropriate for the player to see the next room over. There is only sky above at any time, so…
This design allows us to create descriptions for rooms (as seen from the outside) which will work regardless of where we're looking from. For instance:
This time we're going to assume that the player can see into any room that is on a line of sight within one or two steps of travel.
The obelisk is so large that it can be seen from every room. If we had a number of such large monuments we might want to write a systematic routine to handle them, but this will do for now.
Now, we set things up so that the surrounding areas are described automatically as part of the room description:
But perhaps there are a few rooms where we do not wish that to happen, so we'll build in exceptions for those.
And suppose we want to allow the player to look in any direction:
We also need to tell distant rooms how to describe themselves.
And again, some exception needs to be made for seeing what's in the dip in the ground:
The following is to account for cases where the player types "look toward obelisk" or similar, rather than looking toward a room:
The following is arguably an unnecessary refinement, but the listing of items in the distance gets a bit repetitive unless we vary the sentence structure.
| both | here | there |
| "From here, you make out [a list of mentionable things in the noun] a little way [chosen direction], and, further on, [a list of mentionable things in the second noun]." | "From here, you make out [a list of mentionable things in the noun] [if the noun is not adjacent to the location]some distance [end if]to [the chosen direction]." | "From here, you make out [a list of mentionable things in the second noun] some distance [chosen direction]." |
| "To [the chosen direction] there [is-are a list of mentionable things in the noun], partly obscuring your further view of [a list of mentionable things in the second noun]." | "To [the chosen direction] there [is-are a list of mentionable things in the noun]." | "Quite a way [chosen direction] [is-are a list of mentionable things in the second noun]." |
| "Then [chosen direction] [is-are a list of mentionable things in the noun], and beyond [a list of mentionable things in the second noun]." | "Meanwhile, to [the chosen direction] [is-are a list of mentionable things in the noun]." | "Meanwhile, [chosen direction] in the middle distance [is-are a list of mentionable things in the second noun]." |
| "When you turn [chosen direction], you see [a list of mentionable things in the noun], and somewhat further on [a list of mentionable things in the second noun]." | "When you turn [chosen direction], you see [a list of mentionable things in the noun]." | "If you turn [chosen direction], you see [a list of mentionable things in the second noun] some way off." |
| "Somewhere generally [chosen direction] [is-are a list of mentionable things in the noun], beyond which, [a list of mentionable things in the second noun]." | "Roughly [chosen direction] [is-are a list of mentionable things in the noun]." | "Moreover, in the [chosen direction] distance [is-are a list of mentionable things in the second noun]." |
| "[The chosen direction] shows [a list of mentionable things in the noun] and then [a list of mentionable things in the second noun]." | "And to [the chosen direction] [a list of mentionable things in the noun]." | "Meanwhile, [chosen direction] in the middle distance [is-are a list of mentionable things in the second noun]." |
| "Then, [chosen direction], [is-are a list of mentionable things in the noun], and beyond [a list of mentionable things in the second noun]." | "Meanwhile, to [the chosen direction] [is-are a list of mentionable things in the noun]." | "Meanwhile, [chosen direction] in the middle distance [is-are a list of mentionable things in the second noun]." |
| "Finally, [chosen direction], [is-are a list of mentionable things in the noun], somewhat nearer than [a list of mentionable things in the second noun]." | "Finally, to [the chosen direction] [is-are a list of mentionable things in the noun]." | "Finally, [chosen direction] in the middle distance [is-are a list of mentionable things in the second noun]." |
Now, our ability to view things at a distance should be determined by the size of the things we're trying to see:
We might also want to be able to override, manually, the way distant things are described.
Moreover, proximate things might have special descriptions too.
This is a bit primitive, since if we had an occasion where going was blocked, we could get stuck in a loop. So we would need to be careful, but for this example it won't arise.
Inform's "door" kind provides for a tangible thing which comes between one room and another. A door can be open or closed, and openable or not: it can be locked or unlocked, and lockable or not. Here we create a conventional door, a natural gap in the rocks, and a (fixed in place) wooden ladder:
Most doors are visible from both sides: they are single objects but present in two rooms at once, which raises a number of complications. Inform normally uses the same description looking from each way, which is not very interesting: When? ★ and Whence? ★★★ demonstrate neat ways to describe the two sides differently, and Whither? ★ adds the option for the player to refer to doors as "the west door" and "the east door" automatically.
Neighbourhood Watch ★★ goes further by making a door behave differently on each side: from the "outside" you need a key, but "inside" it opens on a latch. Finally, Garibaldi ★★★ shows how to access information about the two sides of a door.
Higher Calling ★ demonstrates doors which automatically open as needed: though using the Inform extension Locksmith by Emily Short is probably easier and better. Elsie ★★, conversely, demonstrates a door that closes one turn after the player has opened it.
Certain complications apply when characters other than the player have to see and interact with doors that exist in other rooms. Wainwright Acts ★ demonstrates the syntax needed to handle this technically quirky situation.
Something Narsty ★ and Hayseed ★ provide a "staircase" kind useful for vertically arranged, always-open doors like staircases and (fixed in place) ladders.
One Short Plank ★★ implements a precarious plank bridge across a chasm as an open unopenable door.
Windows for climbing through a window from one room to another.
Ropes for portable connections between rooms, much of the development of which could be adapted to handle portable ladders. "Doors" are never allowed to move.
Magic (Breaking the Laws of Physics) for a hat that lets the player walk through closed doors.
Modifying Existing Commands for ways to allow the player to unlock with a key he isn't currently holding.
In a game with many staircases, we might want:
Defining the staircase this way means that we will never be able to get away with (for instance) a folding ladder into the attic which is sometimes closed up. So alternatively we might do
We could then write a rule so that whenever the player types CLIMB [any staircase], the command is diverted to an enter command, while all other doors refuse to respond to such treatment. Still, this kind is now usable, as we see in this trivial example:
But these are refinements for a later chapter.
63. ★ When?Very simple, but quite frequently useful:
Presumably all staircase-type connections between rooms should respond when the player says CLIMB STAIRS (or the equivalent). So
Attempts to climb other types of door will still be treated as useless.
128. ★ Higher Calling"Called" is quite useful in the context of rules about going, since go rules often refer to things other than the noun the player typed. For instance, suppose we want to have doors which politely open when the player tries to pass through them:
A fuller set of such rules is included in the Locksmith extension.
236. ★ Wainwright ActsSuppose we wanted to write rules for a character who will interact with doors in other locations even when the player is not present. This poses a little challenge: doors are actually single objects, and -- with the same shuffling of stage properties that applies to backdrops -- they are moved as needed to represent the door object in whatever room contains the player.
That means that it isn't safe to rely on a phrase like
because, even if Bernard's location is connected by doors to other places, the actual representation of that door may not be "in" Bernard's location, from the model's point of view, at this exact moment.
This does not, of course, mean that we can't ask this question; just that we have to be a little cleverer about how we phrase it. Every door has properties that correspond to the two locations
linked:
We can make this information easier to check with a conditional relation, like so:
And this allows us to write rules that have characters interacting with doors even in the player's absence:
Here we expand on the simple examples When? and Whence?; this time we want the player to be able to refer to doors by their directions, as in "the west door" when the door in question does in fact lead west.
As an added touch, we respond also to the case where the player postulates a door in some direction when there is no such thing at the moment:
Suppose we want a locked door that can be opened with a key, but is also openable by hand without a key from one side only. We start by defining an ordinary lockable door and the key that controls it:
The next part is going to require that we modify the normal operation of the "lock" command. "Lock" ordinarily requires that the player supply two objects: a thing he wants to unlock, and the key he wants to use on it. The full command is LOCK DOOR WITH THE KEY, and Inform will not accept simply LOCK DOOR as locking.
Therefore, we're going to need to create our own new variant on the lock verb (and the unlock verb, while we're at it). The full procedure for this is laid out in the chapters on Action and Understanding, but here is an example:
Here we've created a new action -- locking something without a key -- and we've told Inform to understand LOCK DOOR as this action, rather than an incomplete command to LOCK DOOR WITH SOMETHING.
Now we add some instructions so that the game will not let us use this keyless unlocking command unless we're in the right place or are properly equipped:
This check rule is performed before the keyless locking action succeeds. The first thing we do is try to use the key if the player is outside and has the key: this way, LOCK DOOR will turn automatically into LOCK DOOR WITH THE KEY, under circumstances where that is both possible and necessary.
The second thing is to check whether the player is outside but keyless, and, if so stop the action from being performed successfully. Here we print a failure message followed by the word "instead", which tells Inform that we've substituted some other outcome for the usual performance of the action.
Now we're reasonably sure that the player is only locking keylessly in the case that he is inside the Studio. (We might have to do a more thorough check for this if there were more than two rooms, but as it is, the player can only be in the Stairwell or in the Studio, so if we have ruled out the Stairwell, we are safe.) So now we want to add what happens when locking-without-a-key command succeeds:
That's it. We've just told Inform to make the door be locked. "Now…" syntax will be explained more thoroughly in the chapter on change. But we still haven't described to the player what just happened, so let's provide a description of that, too:
And now we have to do a similar set of things for unlocking:
Some (but not all) of this work is done for you if you like by the Locksmith extension. If you prefer, you can include that extension, then follow the documentation in order to implement the remainder of the scenario. Locksmith takes care of implementing the additional locking and unlocking actions, and provides some other conveniences.
106. ★★ One Short PlankBut indeed, why stop there?
Suppose we want to create an automated door of the sort that closes when it isn't in use. A convenient way is to write a rule that fires "every turn when the sliding door was open". This will be true only if the door was open at the beginning of the turn: if the player just opened it this turn, it stays open, and if it was already closed, it stays closed. Thus:
Suppose we would like to allow the player to view the status of all the doors functioning in the game; and we want to identify those doors by mentioning which two rooms they connect. The following uses some techniques that will be covered in later chapters, but the basic idea may be obvious:
It is more or less arbitrary which room winds up as the "front side" and which as the "back", but in this case it hardly matters.
It would be fairly tedious reading to have a large game full of doors that describe themselves this way. Nonetheless, if we insisted we could use our knowledge of the map as leverage to make every door in the game describe itself automatically.
To do this, we make use of the phrase "direction of (the door) from (a room)" -- in this case, the direction of the door we're looking at when viewed from the player's location. Thus:
Yet a further variation on this, which can automatically understand "the east door" and "the west door" when appropriate, may be found in the example "Whither?".
Calvin Coolidge once described windows as "rectangles of glass." For us, they have two purposes: first, they offer a view of landscape beyond. In the simplest case the view is of an area which will not be interacted with in play, and therefore does not need to adapt to whatever may have changed there:
More interesting is to adapt the view a little to provide a changing picture: a forest may not change much, but a street scene will. Port Royal 4 ★★ allows us to glimpse random passers-by.
The trickiest kind of window allows the player to see another room which can also be encountered in play, and to interact with what is there. Dinner is Served ★★ presents a shop window, allowing people to see inside from the street, and even to reach through.
Vitrine ★ handles the complication of a window misting up to become opaque, and thus temporarily hiding its view.
Second, windows provide openings in walls and can act as conduits. Escape ★★ shows how a "door" in the Inform sense can become a window. A Haughty Spirit ★★★ provides a general kind of window for jumping down out of: ideal for escapers from Colditz-like castles.
Doors, Staircases, and Bridges for a door which can be partially seen through.
Note the "can be transparent" line. Devices ordinarily are not allowed to have transparency or opaqueness, but we can make an exception in this case. Without that line, attempts to change the transparency of the window will fail.
Suppose we want to offer the player a window he can climb through, instead of a boring ordinary door. Our window will be like a door in that it connects two rooms, appears in both places, and impedes movement when it is shut. But we also want to add that we can look through it and see what lies on the other side; and we further want to understand "climb through window" or "jump through window" as attempts to pass through it.
We'll start by defining a couple of rooms and making the window a door between them.
Now we have a "bedroom window" object which can be entered. Now, to catch the case where the player types "LOOK THROUGH WINDOW":
The other side of a door is always defined to be the room that we are not currently in when doing the check. When we are in the bedrooom, the other side will be the grassy slope, and vice versa. "Searching" is the action that occurs when the player attempts to LOOK THROUGH something. (To review what grammar gives rise to what actions, we can always consult the Actions portion of the Index.)
Next we want to cover the case where we climb through the window:
And because "climb window" is understood but "climb THROUGH window" is not, we will have to borrow from the chapter on Understanding to add some new vocabulary to the game (and we'll add Jump too, while we're at it):
Now the final piece: Inform will already keep the player from going through a closed window, but it will say "You can't, since the bedroom window is in the way." This is probably not ideal, so we can replace the instruction thus:
Here's the part that allows reaching through the window.
We replace the usual rule that says the player can never reach into a room with one that more specifically checks whether we are trying to reach through the window. If we aren't, we return the usual refusal. If we are, we return a custom refusal if the window is closed ("You can't reach through the closed window"), but allow access if the window is open.
And the rest is window-dressing.
Our protagonist is imprisoned in Port Royal, waiting out his years, and sometimes through the window of his cell he is able to see someone.
We are, however, obsessive about historical accuracy, so we provide a table of people who really lived in the city, together with the year in which their existence is attested. We want these people to appear in the description only in the year when they are known to have been present. (After all, mortality was high in Port Royal and new people were constantly arriving, so someone's presence one year is no guarantee of their continued existence the next.)
It is possible to look up a row corresponding to, say, a specific year value using "listed in", but repeat through is convenient here because we know that we will never wind up trying to print entries when no row can be successfully selected.
| Trade | nickname | family | Date attested |
| "architect" | "Robert" | "Snead" | 1684 |
| "baker" | "William" | "Wingar" | 1683 |
| "barber" | "William" | "Alcocke" | 1676 |
| "blacksmith" | "William" | "Davidson" | 1679 |
| "bricklayer" | "Samuel" | "Richardson" | 1683 |
| "butcher" | "John" | "Dennis" | 1676 |
| "carpenter" | "John" | "Albert" | 1675 |
| "cabinet-maker" | "Robert" | "Avis" | 1666 |
| "joiner" | "Peter" | "Bartaboa" | 1666 |
| "chandler" | "William" | "Bates" | 1674 |
| "chyrurgeon" | "William" | "Axtell" | 1674 |
| "chyrurgeon" | "Thomas" | "Trapham" | 1678 |
| "combmaker" | "Paul" | "Bennett" | 1673 |
| "cooper" | "James" | "Hall" | 1676 |
| "cooper" | "Henry" | "Pullein" | 1675 |
| "cordwainer" | "George" | "Barnard" | 1675 |
| "cordwainer" | "Edward" | "Skannon" | 1680 |
| "cordwainer" | "John" | "Wilmott" | 1675 |
| "drugster" | "William" | "Mathews" | 1682 |
| "fisherman" | "Richard" | "Collingwood" | 1674 |
| "glazier" | "Thomas" | "Hudson" | 1684 |
| "goldsmith" | "Richard" | "Lord" | 1677 |
| "gunsmith" | "Stephen" | "Massey" | 1664 |
| "hatmaker" | "John" | "Rosewell" | 1683 |
| "ivory turner" | "William" | "Clifton" | 1691 |
| "labourer" | "John" | "Dennis" | 1674 |
| "limeburner" | "John" | "Hardwick" | 1675 |
| "mariner" | "Alexander" | "Bailing" | 1680 |
| "mariner" | "Thomas" | "Bowtell" | 1675 |
| "mariner" | "Peter" | "Claiton" | 1675 |
| "mariner" | "Joseph" | "Cupid" | 1672 |
| "mariner" | "Michael" | "Dunn" | 1675 |
| "mason" | "John" | "Stone" | 1673 |
| "merchant" | "John" | "Agard" | 1680 |
| "merchant" | "David Lopez" | "Narbona" | 1674 |
| "merchant" | "Abraham" | "Langford" | 1675 |
| "merchant" | "John" | "Sweeting" | 1675 |
| "merchant" | "Charles" | "Knight" | 1680 |
| "merchant" | "Cornelius" | "Vandananker" | 1670 |
| "merchant" | "Moses Jesurum" | "Cordova" | 1675 |
| "pewterer" | "Simon" | "Benning" | 1667 |
| "pipemaker" | "John" | "Pope" | 1680 |
| "porter" | "George" | "Paul" | 1670 |
| "poulterer" | "Richard" | "Jeffreys" | 1677 |
| "sailmaker" | "Adam" | "Brewer" | 1671 |
| "schoolmaster" | "Peter" | "Bird" | 1677 |
| "shipwright" | "William" | "Cavell" | 1676 |
| "tailor" | "William" | "Case" | 1676 |
| "tailor" | "Pewter" | "Ebden" | 1683 |
| "waterman" | "William" | "Brocke" | 1674 |
| "waterman" | "Joel" | "Clements" | 1668 |
| "wherryman" | "John" | "Grant" | 1669 |
| "victualler" | "Barnaby" | "Adams" | 1675 |
| "vintner" | "Gabriel" | "Adkins" | 1668 |
| "tavern-keeper" | "John" | "Baldwin" | 1670 |
| "tavern-keeper" | "Mary" | "Dayton" | 1664 |
| "tavern-keeper" | "James" | "Turpin" | 1679 |
| "tavern-keeper" | "Christopher" | "Mayham" | 1664 |
Suppose we have a game in which the player can climb through windows which overlook rooms below. We want him to be allowed to climb out windows to reach a room on the same level or at most one level lower than the one he's on; otherwise, he should get a refusal, saying that he would break his neck.
To figure out the height distance between the start room and the destination room, we might have a repeat loop look at all the directions one has to follow along the "best route" path between the two rooms, and record any ups and downs; then subtract the number of "up" steps from the number of "down" steps, and report what remains.
Now we just have to create windows and some action rules for interacting with them…
Here we must anticipate a little from the chapter on Relations, and provide ourselves with a way of keeping track of how windows and rooms relate to one another:
We could then add rules to allow the player to look through windows and see things in the rooms below, but that would require more material from later chapters.
At any place (room, or inside a container) light is either fully present or fully absent. Inform does not usually try to track intermediate states of lighting, but see The Undertomb 2 ★★ for a single lantern with varying light levels and Zorn of Zorna ★★★ for multiple candles that can be lit for cumulative changes to the light level.
Light can be added to, but not taken away: rooms and things can act as sources of light, by having the "lighted" and "lit" properties respectively, but they cannot be sinks which drain light away. The reason darkness is not a constant hazard in Inform-written games is that rooms always have the "lighted" property unless declared "dark". (We assume daylight or some always-on electric lighting.) A "dark" room may well still be illuminated if a light source happens to be present:
Hymenaeus ★ allows us to explicitly refer to torches as "lit" or "unlit", or (as synonyms) "flaming" or "extinguished".
For light produced electrically we might want a wall switch, as in Down Below ★★, or a portable lamp, as in The Dark Ages Revisited ★.
The fierce, locally confined light thrown out by a carried lamp has a quality quite unlike weak but ambient daylight, and Reflections ★ exploits this to make a lantern feel more realistic.
When the player experiences darkness in a location, Inform is usually very guarded in what it reveals. ("It is pitch dark, and you can't see a thing.") Hohmann Transfer ★★ gives darkness a quite different look, and Four Stars ★★★ heightens the other senses so that a player in darkness can still detect her surroundings. The first of the two examples in Peeled ★ allows exploration of a dark place by touch.
It is sometimes useful to check whether a room that is not the current location happens to contain a light source or be naturally lighted. This poses a few challenges. Unblinking ★★★ demonstrates one way of doing this, so long as there are no backdrop light sources.
Cloak of Darkness ★★★★ is a short and sweet game based on a light puzzle.
Room Descriptions for an item that can only be seen in bright light, when an extra lamp is switched on.
Looking Under and Hiding for a looking under action which is helped by the fiercer brightness of a light source.
Going, Pushing Things in Directions for making it hazardous to walk around in the dark.
Electricity and Magnetism for batteries to power a torch or flashlight.
Fire for a non-electrical way to produce light.
This will be explored more in subsequent examples, but one of the things we can do with carry out rules is extend the function of existing commands so that they do more, or have special effects in specific situations. For instance, suppose we want to have a class of electric light:
This will not affect the behavior of any other devices when switched; it will also not change the way in which switching lights on and off is reported. The player will still see "You switch the sodium lamp on." or the like. In this case that is probably what we want. If we wanted a special way of describing turning on electric lights as opposed to all other devices, we could also add an after rule for the electric light class. Adding this rule to the carry out train does guarantee, though, that in no case will we manage to make the lamp lit without actually making it switched on (or vice versa).
So far so easy. Since we've built the description of its light or darkness into the lamp's description, though, we may want to get rid of the "…is switched on" line that automatically follows when we look at something. For this we do need to borrow from a later chapter:
Suppose we have a situation where the player is in darkness, but is allowed to feel and interact with (except for examining) any large objects. In that case, we write a scope rule that puts those large objects into scope all the time, and trust the "requires light" aspect of verbs like examining to prevent the player from doing any actions that he shouldn't:
Sadly, because the grape is small, the player will never encounter this horror.
Alternatively, suppose we have a situation in which the player can use one command to interact with a kind of thing that isn't normally in scope. It's usually most convenient to write the "understand" rule appropriately rather than use the scope activity.
(Note that we define "inquiring about" as applying to one *visible* thing; otherwise we would be required to be able to touch the catsuit in order to inquire about it. More on this restriction may be found in the Advanced Actions chapter on the topic of visible, touchable, and carried things.)
All this said, there do arise certain complex situations when we want an activity-specific scoping.
26. ★★ Down BelowSuppose we want to have a room with a light switch. Turning the switch off makes the room go dark; turning it on restores the light. This kind of switch is an obvious candidate as a device.
Here we define our light switch, and we also make it start out as "switched on". The Terrifying Basement will also start out lit (as all rooms do, by default, unless we specifically say that they are dark). We further say that it is fixed in place to avoid the ludicrous possibility of the player picking it up and carrying it away.
Next we add some instructions to control how turning the light switch on and off affects the room light. These borrow from later chapters on actions, but the gist may be obvious anyway:
Inform already has the idea of light and darkness built in; we will see more about this later, and the Phrasebook (in the Index tab) also contains a list of all the adjectives (lighted, dark, etc) which are important to use here.
Speaking of the Index, the Actions tab contains a list of all the grammar that can be used to activate a given command: for instance, the switching action responds to "switch [something]" or "turn on [something]". In this case, we may want to give the player an extra option or two. It would be pretty natural for a player to try >FLIP SWITCH, so let's add that in:
The nuances of this will be explored in the chapter on Understanding. What is useful to know here is that we have taught Inform to understand that >FLIP LIGHT SWITCH means to turn it on when the switch is already off; if the switch is already on, FLIP SWITCH means to turn the switch off. Depending on the kind of device we are modeling (button? lever? dial?), we might want to write similar lines for commands such as PUSH, PRESS, PULL, TURN, and so on.
Finally, we need to deal with a special case. In general, the player cannot interact with other things in a dark room because he can't see them, but if we adhered strictly to this it would be impossible for him to find the light switch to turn it back on. So we need something from the chapter on Activities to change this:
Inform automatically keeps track of light and darkness, handling such questions as whether a room is lit, whether the player can see any light sources, etc., and then managing the descriptions accordingly. When the room is dark and no light sources are visible, the player is said to be "in darkness".
If we don't specify otherwise, Inform will describe our surroundings in a dark room thus:
This is fine in many situations, but we may sometimes want to replace this phrase with something else.
And now a few minor refinements so that we can see what happens when one room becomes dark and the other light:
Suppose we're simulating a situation where the player needs to travel through lit areas only, but we want to give him some hints about which way might be safe. Here we'll find our best route through light-filled rooms.
The slightly tricky part is that it's not necessarily easy to tell whether a room has a lamp in it. We may say "if the Crypt is lighted", but that only tells us whether it has been declared to be inherently lighted or dark, not whether it happens to contain a light source that the player would be able to see if he went in.
The easiest way to get around this is to create an object -- the light-meter; place it in the target location; and check whether it "can see" a lit object. This preserves all the usual rules about open and closed containers, transparency, etc.
That done, we're free to use our best-route phrases to choose a particular route.
An important word of caution: this method would give false negatives if there were a backdrop lightsource, such as the moon, providing light to the Upward Path. This is because backdrops are actually moved around the map by Inform during play, following the player around. So if the moon backdrop is in the Crash Site with the player, it will not be in the Upward Path as well -- even if it's scheduled to move there as soon as the player does.
347. ★★★ Zorn of Zorna"Cloak of Darkness" is a brief example game that has been implemented in nearly every IF system currently used. It hasn't got much claim to complexity or richness, but it does exemplify many of the standard things one might want an IF language to be able to do: define descriptions and the results of actions, assign synonyms to nouns, create new verbs, handle darkness, track repeated acts, and so on.
Here is what the game looks like in Inform:
Whatever room we define first becomes the starting room of the game, in the absence of other instructions:
We can add more rooms by specifying their relation to the first room. Unless we say otherwise, the connection will automatically be bidirectional, so "The Cloakroom is west of the Foyer" will also mean "The Foyer is east of the Cloakroom":
Inform will automatically understand any words in the object definition ("small", "brass", and "hook", in this case), but we can add extra synonyms with this sort of Understand command.
This description is general enough that, if we were to add other hangable items to the game, they would automatically be described correctly as well.
We could if we wished use a number to indicate how many times the player has stepped on the message, but Inform also makes it easy to add descriptive properties of this sort, so that the code remains readable even when the reader does not know what "the number of the message" might mean.
This second rule takes precedence over the first one whenever the message is trampled. Inform automatically applies whichever rule is most specific:
This command advances the state of the message from neat to scuffed and from scuffed to trampled. We can define any kinds of value we like and advance or decrease them in this way:
This defines an object which is worn at the start of play. Because we have said the player is wearing the item, Inform infers that it is clothing and can be taken off and put on again at will.
And that's all. As always, type TEST ME to watch the scenario play itself out.
It is too easily assumed that room descriptions are what the player sees, but as The Undertomb ★ demonstrates, they might just as easily include ambient sounds.
So Inform's "listening to" action is the audio equivalent of "examining", rather than "looking". Despite this the player can type LISTEN, which Inform understands as listening to the everything in the location at once. A simple but effective way to handle this is shown in The Art of Noise ★★★.
Four Stars 2 ★ adjusts the idea of "visibility" to make it behave differently for listening purposes: this introduces a formal idea of "audibility".
Lighting for heightened hearing in darkness, and the rest of "Four Stars".
This example creates a kind of room, "dead end", and gives each a textual description called its "river sound". Note the use of a text substitution to fill in the appropriate river sound text in each dead end.
As we have seen, a well-written understand rule will often solve the problem of allowing the player to apply specific actions to objects not normally in scope. When we need to adjust scope for some other reason than reading the player's command, though, "deciding the scope of…" may come in handy.
For instance, suppose we wanted to extend Four Stars 1 to add a tomcat on the balcony that will be heard whenever the player listens from the next room, as in:
To do this, we need to make sure that in the rule that assembles our listening description,
now includes the tomcat in the "list of audible things which can be touched by the player".
To this end, we're going to change the way we assess scope, but only during the listening action. Otherwise the tomcat remains in the other room and off-limits. The new source text is marked out below:
Here is our addition:
And now our threat to the player's peace:
From here we continue with the same scenario as before:
Of course, this new version is less happy for the player, as we haven't included any way to silence the cat.
95. ★★★ The Art of NoiseThis example involves redesigning the LISTEN command, removing its built-in function and replacing that with something more ambitious. We will learn more about how to do this later on.
Out of doors, nature is seldom still. Clouds scull by at random, as in Weathering ★, and provide some variety in what would otherwise be lifelessly static room descriptions. In much the same way, passers-by and other diversions make a city street a constant bustle: see Uptown Girls ★★★ for this human breeze. A more nagging sense of atmosphere can be experienced in Full Moon ★.
Orange Cones ★★★ offers traffic that is present on every road in the story unless a room is marked off with orange cones -- and this is allowed to change during play.
Night and Day ★ and Totality ★★ each schedule celestial events to provide a changing display in the sky above, and this time running like clockwork rather than at random.
Scene Changes for meteors and a moon-rise.
Suppose we want to have a sequence of nights and days in our game, with one scene to govern each daylight condition.
Notice that our two conditions for the beginning of Night are not in conflict: it will be night-time when the game begins, and then night will also recur every time the Dusk scene ends.
If we run this example and then have a look at the scenes index, we'll see that the cycle is listed through thus:
with the second "Night" in italics, to indicate that it is a repetition of the same scene that has already been listed above.
144. ★★ TotalityFirst we define the events, and then we create a phrase to schedule them:
Now we make use of the new phrase:
We shall see much more about creating phrases later. Their advantage is that they enable a complicated sequence of operations to be given a meaningful name, and that they can be re-used many times as needed.
120. ★★★ Orange ConesBecause we can invent our own adjectives (see the chapter on Phrases), we can make the conditions for a backdrop as simple or as complicated as we like.
In this scenario, we want the player to be able to take, move, and drop orange traffic cones to seal off one street or another. So we create our own "accessible" adjective as follows:
…and now
will tell the traffic backdrop where to appear.
That accomplishes everything we set out to do, but let's add a very simple puzzle to test it out with:
And finally, a couple of features from the Activities chapter to make the output more elegant:
Suppose we have an urban space we want to populate with random passers-by. These should have a range of characteristics and not always be described in the same way; and once the player has noticed one, he should be able to look at her further, until another pedestrian crosses his path.
It gets a little annoying to have a random event occurring every single turn of play, so let's introduce some randomness to determine how often the message appears:
| event |
| "Slowly [a passerby] strolls by, turning to look at you as she passes." |
| "Some [passerby] nearly bumps into you." |
| "You dodge to avoid [a passerby]." |
| "You weave around [a passerby], who has stalled to look into a window." |
| "There's a ruckus as one of the ubiquitous taxis nearly collides with [a passerby] crossing the street." |
| "[The passerby] beside you waves to a friend across the street." |
| "To your left, [a passerby] drops her purse, and swears as she retrieves it." |
At this point we borrow some techniques from later to describe the woman with a random combination of characteristics, and to let the player refer to her by those traits:
If we also wanted each of those combinations to mean some more specifically-described woman:
| hair | height | grooming | description |
| red-headed | tall | messy | "An older woman with long red hippie-hair poking out of a ponytail in straggles, and bent to hide how tall she is." |
| red-headed | medium-height | messy | "A shaggy red-head with shingled hair." |
| red-headed | short | messy | "Almost an urchin, and very young, with ginger hair and a smudged nose and far too many freckles." |
| red-headed | tall | tidy | "A precise career woman with henna-red hair." |
| red-headed | medium-height | tidy | "Her hair is red in the way that lollipops and fire trucks are red: not by nature but by art. The rest of her clothing is pretty ordinary, though." |
| red-headed | short | tidy | "Thin and small in every sense, with chin-length red-hair. Even high heels do not bring her head much above your shoulder." |
| brunette | tall | messy | "A Juno-esque woman with dark hair, wearing something resembling a tent." |
| brunette | medium-height | messy | "An unremarkable woman with dark brown hair and the aura of needing a wash." |
| brunette | short | messy | "There are mustard stains on the t-shirt of this short brown-haired woman. Estimated age ca. 40. Possibly homeless." |
| brunette | tall | tidy | "A leggy brunette in business attire." |
| brunette | medium-height | tidy | "Medium-height, brown-haired, generally nondescript." |
| brunette | short | tidy | "A neat little dark-haired girl." |
| blonde | tall | messy | "A tall blonde of about thirteen who looks as though she has not yet figured out how to get her wardrobe to catch up with her rate of growth. Her t-shirt and her pants are too short." |
| blonde | medium-height | messy | "Black leather pants and the wall-o-hair look." |
| blonde | short | messy | "One of those shocking platinum blonde types, with a tiger-patterned skirt. Reeally trashy." |
| blonde | tall | tidy | "Elfin and severe, with perfectly straight hair falling to the middle of the back." |
| blonde | medium-height | tidy | "A rounded, Marilyn-esque blonde." |
| blonde | short | tidy | "Pin-precise in a blue-and-white striped suit and a boyish haircut." |
A story that makes heavy use of time may want to give the player a hint that time is important – and an easy way to keep track of how it's going – by adding the current time to the status line, instead of the score. To do this, we would write
All else being equal, time passes at a rate of one minute per turn. But this need not be so: we can imagine a story where turns take much less time, or much more; or a story in which the passage of time was sometimes suspended, or one in which different actions required different amounts of time to perform.
Situation Room ★ provides a way to print 24-hour time, while Zqlran Era 8 ★★★ implements a completely new measurement of time, for a story set on an alien world.
Uptempo ★ and The Hang of Thursdays ★★★ speed up time's passage: turns take fifteen minutes in the former, or a quarter day in the latter.
Timeless ★ makes certain actions instant, so that they don't count against the clock; this is sometimes useful in timed situations where the player needs to review the situation before going on with a tricky puzzle. Endurance ★★ systematically extends this idea to allow us to assign different durations to any action in the story. The Big Sainsbury's ★ goes the opposite direction, and meticulously adds a minute to the clock for all implicit take actions, just so that the player isn't allowed to economize on moves.
An alternative approach to time is not to tell the player specifically what hour of the day it is at all, but to move from one general time period to another as it becomes appropriate – when the player has solved enough puzzles, or worked his way through enough of the plot. To this end we might use scenes representing, say, Thursday afternoon and then Thursday evening; then our scene rules, rather than the clock, would determine when Thursday afternoon stopped and Thursday evening began:
Though this gives time a loose relation to the number of turns played, it feels surprisingly realistic: players tend to think of time in a story in terms of the number of significant moves they made, while the random wandering, taking inventory, and looking at room descriptions while stuck don't make as big an impression. So advancing the story clock alongside the player's puzzle solutions or plot progress can work just as well as any stricter calculation.
Passers-By, Weather and Astronomical Events for cycles of day and night scenes.
Waiting, Sleeping for commands to let the player wait until a specific time or for a specific number of minutes.
Clocks and Scientific Instruments for clocks that can be set to times and that have analog or digital read-outs.
Timed Input for discussion of extensions allowing real-time input.
Though Inform normally prints times in AM/PM terms, it stores the hours and minutes as 24-hour time; so, if we like, we can easily extract that information again thus:
Implicit takes are a convenience to players; in general, we would like to avoid asking players to type any more obvious commands than strictly necessary, while allowing the computer to guess as much as it safely can.
Occasionally, though, we have designed a timed puzzle in which the player has a limited number of moves in which to accomplish his objectives. In that case, the implicit take complicates matters, because it means that a player who types
gets away with a spare move compared to the precise but naïf dupe who types
…and really, that doesn't seem quite fair. The way to fix this problem is to fill in the extra minute on the clock during the implicit take; and that is indeed what we do in the following example.
Suppose a game in which all actions take a very long time. Here's a simple implementation:
This works fine as it stands, but we may run into some difficulty with it if we add scheduled events:
Time is counted forward after the schedule has already been consulted, so that only the 9:30 AM event happens between 9:30 and 9:45; the next two appear to occur between 9:45 and 10:00 AM, and the 9:50 AM event is not reported until the 10:00 AM to 10:15 wait. To get around this, we might schedule events only on the fifteen-minute mark when we want them to occur. Alternatively, we might try instead
This time our revised time-advancing rule is listed just before the event scheduler, not just afterwards.
408. ★ TimelessIn a game with tight timing, it is sometimes friendliest to the player to let him LOOK and EXAMINE as much as necessary without being penalized.
Now we need a rule which, just at the right moment, stops the turn sequence rulebook in the cast of our new fast-acting actions:
Thus the rest of the turn sequence rulebook is omitted for looking or examining: in effect, they become out-of-world actions like "saving the game". If we wanted to add, say, taking inventory to the list of instant activities, we would just need to define it as acting fast, too.
Now the scenario for testing:
Here we move to a systematic way of giving different durations to different actions, including even variations on the same act -- so that for instance climbing a steep hill might take several minutes more than other going actions. We do this by setting a number, "work duration", to represent the number of minutes consumed by a given action, and then consulting a rulebook to find out how long the past turn's action should take. By default, an action will take 1 minute.
We'll start by emulating the behavior of "Uptempo": each turn we'll set the clock forward most of the way, then check to see what has changed since the last turn, print any relevant events, and only then set the clock forward the final minute. The exception is when an action is set to take no time at all; in that case, we'll skip the rest of the turn sequence rules entirely.
Now we need to borrow from a later chapter to make these instructions apply to the passage of time:
Suppose that our game takes place on an alien planet that does not follow Earth time. On this planet, we want to track time with different units. We also want time to advance in those units, and we want to be able to set a schedule of timed events.
Inform automatically supplies a way to say a new unit, which will look similar to the format in which we defined that unit in the first place. But we can (as shown here) create our own alternative say phrases to express the units in other ways as well.
Next, we need to meddle with time advancement so that time is tracked in Zqlran date rather than in minutes. This requires borrowing a trick from a later chapter, to replace Inform's built-in time handling with an alternative time handling rule of our own:
| era | event |
| 8-24 | "A wisp-thin cloud blows rapidly across the face of Nepenthe, the lesser of the two green moons." |
| 8-28 | "The cloud across Nepenthe clears." |
Note that we could if we wished use a different device for scheduling events: this one simply prints text at scheduled eras, but we might also (for instance) make the event entry be a rule for Inform to follow, and tell Inform to carry out that rule at the scheduled time.
Sometimes we want to arrange a scene in which something goes on in the background (as though it were a movie playing) while the player goes about his business; or where a series of things has to happen before the player gets to the end.
The simplest way to arrange background events for a scene is to write the sequence of events into a table and work our way through it, printing one line per turn, until the scene runs out. Day One ★★★ does exactly this.
At other times, we want a scene to last as long as it takes the player to do something. Entrapment ★★ lets the player poke around and explore as much as he likes, but ends as soon as he has accomplished the scene's goal – which, unfortunately for him, is to get into an embarrassing situation so that another character can walk in and make fun of him. The Prague Job ★ has a scene that requires the player to do a more specific set of tasks, but nags him and hurries him along until he's done.
Bowler Hats and Baby Geese ★★★ assumes that our story is going to be assembled with a number of scenes, some of which will need to prevent the player from leaving the location until the scene is complete: it thus defines a "restricted" property for scenes, so that all such elements of the plot will work in the same way.
For more complex sorts of scripts and schedules, it may be worth consulting the extensions.
Characters Following a Script for a character whose conversation with the player is scripted to follow a pattern and then conclude.
Suppose we want to remind the player that he doesn't have all the time in the world, by starting to nag him when he's nearly, but not entirely, done going over his inventory in preparation for a job.
The power of scenes lies in their ability to watch for general conditions and move the narrative along whenever these are fulfilled. Instead of waiting for the player to do one specific thing, the game waits for the world to be in a certain condition, before moving to the next stage of the plot.
For instance, suppose we have a story in which the player has been captured for doing something inappropriate at court and is brought in to await a meeting with a palace official. We want to give the player a few minutes to stew, and we want the scene to end with him doing something mildly peculiar or embarrassing, and the official catching him in the act. So we tempt him into trying any of a number of different kooky activities, and just wait until he falls into the trap…
…and this scene might lead to another, and so on.
The purpose of an open-ended scene like this might be puzzly or narrative: we might be waiting for the player to get a puzzle solved, or we might be waiting for him to fulfil some plot condition that must be met before we can go on.
159. ★★★ Bowler Hats and Baby GeeseScenes can have properties -- a fact that is very useful when it comes to writing a series of scenes that all need to act alike in some respect.
Suppose we have a plot that features a number of scripted scenes, where we need the player to stand still and wait while the events of the scene play out. One way to set this up is to create a property for such scenes -- let's call them "restricted" -- and then write a rule that keeps the player in place while the scene happens:
And now let's set up our restricted scene. In it, a clown is going to turn up wherever the player is (it doesn't matter where on the map he's gotten to at this point) and do a performance; the player will not be able to leave the area until the performance completes. We'll start with the setting:
…And now the scene itself:
| event description |
| "A clown with a purple polka-dot bowler hat strides into the vicinity and begins to juggle baby geese." |
| "While the clown juggles, the baby geese visibly grow older and larger. The clown becomes unnerved." |
| "In an attempt to resolve the problem, the clown reverses the direction of his juggling. The geese revert to goslings." |
| "The goslings become smaller and smaller until the clown is juggling goose eggs[replace eggs]." |
| "The clown throws all the eggs into the air at once and catches them in the bowler hat. He takes a bow; the audience applauds. As a final gesture, he upends his hat to release a perfectly cooked omelet." |
Here we use a table (see subsequent chapters) to keep track of all the events we wish to have occur during the course of the scene.
| event |
| "'Welcome to Precolumbian Archaeology 101,' thunders Dr Freitag from the front of the class. 'Miss-- yes, you in the back. If you can't find a free seat, how are you going to find Atlantis? Sit down or leave. Now. Thank you.'" |
| "Freitag stands behinds his desk and lines up the pile of books there more neatly. 'It has come to my attention over previous years that there are two sorts of person who enroll in my class,' he says. 'Some of you will be members of the swim team or women's lacrosse players who have a distribution requirement to fulfill and are under the mistaken impression that archaeology must be easier than psychology. If that description applies to you, I advise you to drop the class now rather than at the midterm break. Under absolutely no circumstances will I ever sign a withdrawal form for someone who is crying at the time. Make a note of that, please.'" |
| "'The second sort of person,' Dr Freitag says, getting another wind. 'Yes, the second sort of person takes this class because she imagines that it is going to lead to adventure or possibly to new age encounters with dolphins.' His eye moves over the class, lingering an especially long time on a girl in a patchwork skirt. 'You should also leave now, but since you are probably lying to yourself about the reasons you're here, you will probably not heed my warning and we will be doomed to a semester of one another's company nonetheless.'" |
| "'Whatever you may tell yourself, you are not here to gain a deeper understanding of the world or get in touch with yourself or experience another culture.' He paces before the first row of desks, hammering on them one at a time. 'I know you probably wrote an admissions statement saying that that is what you hoped to do. Well, too bad. It is not inconceivable that some of you, somehow, will muddle towards a deeper understanding of something thanks to this class, but I am not holding my breath, and neither should you.'" |
| "Freitag takes a breath. 'No, my dear freshwomen, what you are here to do is learn facts. FACTS. Facts are unpopular in this university and, I am unhappily aware, at most of the institutions of inferior preparation from which you have come. Nonetheless, facts it will be. I will expect you to learn names. I will expect you to learn dates. I will expect you to study maps and I will expect you to produce evidence of exacting geographical knowledge on the exams. I will expect you to learn shapes of pottery and memorize masonry designs. There are no principles you can learn which are more important or more useful than a truly colossal bank of facts right there in your own head.'" |
| "'I do not ever want to hear that you do not need to learn things because you will be able to look them up. This is the greatest fallacy of your computer-semi-literate generation, that you can get anything out of Google if you need it. Not only is this demonstrably false, but it overlooks something phenomenally important: you only know to look for something if you already know it EXISTS. In short there is no way to fake knowledge, and I am not going to pretend there is.' He smiles in lupine fashion. 'This class is likely to be the most miserable experience of your four years in university. Clear?'" |
| "Everyone is silent." |
| "The lecture is interrupted by the shrill of a bell." |
And then we define the scene so that it ends when the table runs out.
One advantage of this is that we can then edit the events in the scene by changing just the table; the scene will always run the right length and end on the turn when the last event occurs.
And to add a few additional details:
Notice the careful phrasing of "doing something other than…" so that we do not mention the objects; if we had written "something other than listening to something…", the instead rule would match only action patterns which involved a noun. We state the rule more generally so that it will also match nounless commands such as JUMP and SING, since Freitag will probably take a dim view of those as well.
We can use a schedule of events to give some life to our environment: if we have a town setting, for instance, it makes sense for shops and libraries to open and close at set times; this is just what we find in IPA ★★.
Air Conditioning Is Standard ★★★★ has characters who follow a timed schedule of events to interact with each other, while the player mostly wanders around missing out on the action. (Sometimes life is like that.) The same effects could have been achieved with scenes instead of clock times, but there are occasions when we do want to plan our characters' behavior to the minute rather than waiting for the player to be in the right place to observe it: in a murder mystery or a time-travel story, the exact timings might be quite significant.
We may also want to add events to the schedule during play, as in
Similarly, we can schedule things during play to happen at a specific time of day, as shown in Hour of the Wren ★★★.
Scene Changes for more things that arrive at pre-determined times.
Ships, Trains and Elevators for a train that follows a schedule, carrying the player along if he is aboard.
Suppose we wanted a game set in a living town, with locations opening and closing at different times of day, and business carrying on as usual. The point might be to force the player to plan his itinerary carefully to hit the right spots at the right times; or we might be writing a more contemplative piece, where part of the enjoyment came from just watching the characters wander around doing their daily business…
Here we allow the player to set the time at which some future event is going to happen, rather than letting the game decide. We'll need to borrow the syntax for defining new actions from a later chapter:
In a plot that takes place over multiple locations or has several distinct scenes, we may want to move the player or change the scenery around him. Age of Steam ★ brings a train on and off-stage as the plot requires. Meteoric ★★ similarly brings a meteor into view at a certain time of day, showing off several implementations depending on whether or not the player is supposed to be able to refer to the meteor after it has gone.
Entrevaux ★★★ constructs an organized system such that all scenes have their own lists of props and associated locations, and props are moved on and off automatically. Scene changes are also announced with a pause and a new title, such as "Chapter 2: Abduction".
Space Patrol – Stranded on Jupiter ★★ inserts an interlude in which the player's possessions and clothes are switched for new ones and the player moved to a new location – and then put back where he started from.
Flashbacks for more ways to move the player from one level of reality to another.
The following source is very short and simple, yet it already feels surprisingly interesting in play, because something is going on which the player does not control but must observe. The single scene both starts and finishes.
The game below begins at half past eleven, and one turn later, it's meteor time:
Or for something a little slower-moving and with no after-image:
Though we should not really use Earthly time-keeping, since the Martian day is about half an hour longer than ours.
158. ★★ Space Patrol - Stranded on Jupiter!American radio adventure series of the 1950s were unobtrusively sponsored by breakfast cereals, as the following modest example demonstrates. Note that the scene-changing for the commercial break needs to know nothing about the actual programme it breaks into: if Part I were replaced with a different Space Patrol episode, Part II need not be changed at all.
| nope |
| "You can't go that way in the limited universe of this sponsored message." |
| "Or that way." |
| "You've already tried that!" |
| "Why would you want to walk away when you have an alluring bowl of Ricechex right here?" |
Episode 57 of "Space Patrol" was actually called "Iron Eaters Of Planet X", just in case the reader feels that any of the foregoing unfairly traduces a work of thoughtful science fiction.
163. ★★★ EntrevauxFor some games, it makes sense to organize the entire game around scenes rather than around locations, moving the player when a new scene begins and laying out new props.
To this end, we might extend Inform's default handling of scenes so that each scene has properties to indicate prop lists and locations, and move objects in and out of play automatically as the scenes change. For instance:
The starting location is the room to which the player should be moved; scenery props are things that need to be put there when the scene begins; inventory props, things that are given to the player when the scene begins; and the description some printed text to introduce the new scene. We may still occasionally need to have recourse to special "When the Dancing-Lesson begins…" rules for individual scenes, but for the most part this allows us to set scenes up in a consistent and predictable way.
Another point that might be slightly less obvious: sometimes we want to announce a change of location to the player when the scene starts, and sometimes we don't. In particular any scene that starts "when play begins" should probably not explicitly describe the entered room, since that would duplicate the description automatically produced on the first turn of play. So we add a property to track whether any given scene should be announcing its location:
And let's say that we also want to announce each new scene as another "chapter" of the game in play, with a pause before the scene begins.
Here we include "Basic Screen Effects" because it will allow us to pause the game for a keypress, then clear the screen before each new chapter:
At the end of each scene, we strike the set and remove all the loose objects from play.
The viewpoint character may often need to remember events long past. The easiest way to do this is with a cut-scene, in which at some relevant point we pause the story and print a long passage of text describing the memory. Because large amounts of text can be hard for the player to take in, we may want to include some pauses in the presentation of this material; this facility is provided by the Basic Screen Effects extension by Emily Short, and might work something like this:
The "pause the game" phrase in the same extension offers a more dramatic pause that also clears the screen before printing new text.
Cut-scenes are easy to implement but should be used sparingly, since players often get impatient with long uninteractive passages. A slightly more deluxe implementation might insert an interactive scene that simply happens to be set in the past, before going on with another scene set "now"; and, indeed, some IF abandons the idea of "now" entirely, presenting pieces in a non-chronological order and letting the player work out how the sequence works together.
The most challenging case to implement (though still not very hard) is the one where we remove the player from one scenario, let him play through a flashback with past possessions and clothing, and then restore him to the same situation he left, with all of the same possessions and clothing. Pine 3 ★★★ shows how to do this: the code to change the player's status is isolated at the end of the example, and might fruitfully be reused. Pine 4 ★★★ expands on the same idea by adding another flashback scene, demonstrating one that can be visited repeatedly and one that can be seen only once.
Scene Changes for more uses of stripping and restoring the player.
Background for other ways of introducing information that the player character already knows.
Alternate Default Messages for comments on how to change the tense of an interactive scene.
This is mostly a repeat of what we have already seen, but for the sake of producing a playable scenario, we include it. The new material appears at Part 2.
| topic | reply | quip |
| "dream/dreams/nightmare/nightmares/sleep" | "'Sleep well?' you ask solicitously. "'Ghastly nightmares,' she remarks. You nod politely." | 'Not really,' she replies, edging away from you. So much for that angle." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'So,' you say. 'This is a little weird since we just met, but, um. Would you like to get married?' "'I, er,' she says. 'I hope I'm not supposed to marry you or something.'" | She looks at you nervously. 'Do I have to?'" |
| "marriage/love/wedding/boyfriend/beau/lover" | "'I was told I was going to marry you and inherit the kingdom,' you say, apologetically. 'Would that be very bad?' This could be awkward, considering your family circumstances -- you did promise your mother that everything would be better, after this -- 'Oh, it's not you -- I'm seeing someone,' she says, smiling quickly. "'Do you think I could go look for someone? I'm seeing him, you see, and I think I've been... sick... for a while, so he might be worried.' | You try to think how to point out that it's been a hundred years since she last saw her boyfriend." You try to think how to point out that it's been a hundred years since she last saw her boyfriend. And try not to think how awkward things would be in your family if she refuses to marry you." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'You've been up here for a hundred years,' you say. An unpleasant thought occurs to you. 'Was your young man in the castle somewhere?' "She goes to the window and looks out at the now-fading thicket of briar. 'That took a while to grow,' she observes. 'I've been up here longer than I thought.' | She shakes her head mutely." You shrug, uncomfortable." |
So far we haven't much of a chance to affect matters and make them better. Suppose we'd like to add an element to the conversation where we're allowed to tell Beauty about past events -- and explore them a bit; and if the first retelling doesn't go quite as planned, we're allowed to revisit these scenes to hit them with a bit more emphasis.
Once known, a fact remains known permanently -- this could be useful if we wanted to make some rules about how Beauty acts when she knows different information. By contrast, a fact is only "current" if it is the last thing discussed. Since a player can mention a fact over and over, he can make it "current" again and again, and thus reactivate the flashback.
| topic | reply |
| "poor/poverty/family/money/mother/circumstances" or "family circumstances" or "my family/mother" | "[if family circumstances is unknown]'I wish you'd give some thought to marrying me. You see,' you say, your jaw tensing. 'I wouldn't ask if it weren't for my [family circumstances]...'[otherwise]'I don't think you fully understand the [family circumstances],' you say.[end if]" |
This "After printing the name…" rule will be explained later in the chapter on activities; for now, it is enough to know that whenever family circumstances is mentioned in the table of flashback material, this rule will automatically be called. Now the terms under which the flashback happens:
Note the "recurring" here: we want the player to be able to revisit this scene as needed.
And the following is the same as in the Space Patrol example as well: we need a systematic way to remove the player's possessions, then put everything back when the flashback is over:
Because we haven't changed the endings of the "Marriage Proposal" scene, there is still only one way for this scenario to work out; but at least now the player has the opportunity to alter Beauty's attitude a bit (or not) before the game is done.
167. ★★★ Pine 4Suppose in addition to our pathetic little family history, we have another secret to convey to the Princess, this one a little more peculiar. She either gets it or she doesn't; once she gets it, we do not revisit that flashback, though it is still possible to keep visiting the poverty flashback.
| topic | reply | quip |
| "dream/dreams/nightmare/nightmares/sleep" | "'Sleep well?' you ask solicitously. "'Ghastly nightmares,' she remarks. You nod politely." | 'Not really,' she replies, edging away from you. So much for that angle." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'So,' you say. 'This is a little weird since we just met, but, um. Would you like to get married?' She looks at you nervously. 'Do I have to? I mean, I'd rather not.' "'I, er,' she says. 'I hope I'm not supposed to marry you or something.' Uh oh." | Well, this could get prickly fast." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'I was told I was going to marry you and inherit the kingdom,' you say, apologetically. 'Would that be very bad?' This could be awkward, considering your family circumstances -- you did promise your mother that everything would be better, after this -- 'Oh, it's not you -- I'm seeing someone,' she says, smiling quickly. "'Do you think I could go look for someone? I'm seeing him, you see, and I think I've been... sick... for a while, so he might be worried.' | You try to think how to point out that it's been a hundred years since she last saw her boyfriend." You try to think how to point out that it's been a hundred years since she last saw her boyfriend. And try not to think how awkward things would be in your family if she refuses to marry you." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'Do you think you could consider alternatives if he's no longer interested in you?' you suggest. She gives you the look of a wounded squirrel. 'My father might not approve of my love for the kitchen boy, but his heart is faithful and true!' she exclaims. "'I don't expect you to understand,' she says in a low whisper. 'I know it is not considered proper for a princess to love -- and such a one as my William, who works in the kitchen --' Her glance dares you to laugh. '-- but I cannot marry you without telling you this truth.' | 'Right; supposing that he's still around, I'm sure that his love won't have faded,' you say, considering your fingernails. Maybe you'd better come clean with her about your identity, after all: she might be more favorably inclined if she understood that you won't interfere in her base-born romances." Right then. Perhaps you'd better tell her your secret, in exchange?" |
| "marriage/love/wedding/boyfriend/beau/lover" | "'You've been up here for a hundred years,' you say. An unpleasant thought occurs to you. 'Was your young man in the castle somewhere?' "She goes to the window and looks out at the now-fading thicket of briar. 'That took a while to grow,' she observes. 'I've been up here longer than I thought.' | She shakes her head mutely." You shrug, uncomfortable." |
| topic | reply |
| "poor/poverty/family/money/mother/circumstances" or "family circumstances" or "my family/mother" | "[if family circumstances is unknown]'I wish you'd give some thought to marrying me. You see,' you say, your jaw tensing. 'I wouldn't ask if it weren't for my [family circumstances]...'[otherwise]'I don't think you fully understand the [family circumstances],' you say.[end if]" |
| "secret/identity/gender/girl/female/woman" or "secret identity" or "my secret" or "my secret identity" or "my gender" | "[if dramatic revelation ended in failure]'Look,' you say, trying again. 'Pay attention: I need you to understand my [secret identity].'[otherwise]You clear your throat and allow your voice to stray upward, into its natural register and out of this husky false tenor you've been affecting. 'There's, er, something you should know about my [secret identity],' you say...[end if][if dramatic revelation ended in success] She looks impatient. 'I get it, you know,' she says. 'I'm not stupid.'" |
This time, we're waiting for the princess either to understand or not understand -- so we don't want to rerun the scene once it has happened successfully.
And now, since we don't really want to return to the rest of the 'marriage proposal' scene once she has learned our ID:
Notice that we moved the re-activation rule down here so that the Compromise Proposal rule would fire first. There are other more complicated ways of handling order of every turn rules than by relying on text sequence alone; but we will save that for a later chapter. For now it is sufficient to depend on the order in which the rules are declared.
| topic | reply | quip |
| "girls/me/women/female/truth/identity" | "'Marrying me would be no interference,' you go on. 'You could carry on whatever romances you wished, without your father noticing.' (Probably. You'll let the pragmatic details of this work themselves out later, and hope that any children she has will look vaguely like you.)" | "'Girls can't rescue people.' 'Wrong,' you say, feeling a little annoyed. 'But you see why marrying me wouldn't be an interference. You could carry on whatever romances you wished, without your father even noticing.'" |
| "king/man" | "'If you're thinking that a woman can't be the prince -- and then king -- well, there was a woman Pope, once.' "The crease in her forehead does not go away. 'But if everyone thinks you are a man... later you would be king!' | She looks awed." Before she can go on, you say, 'There was a woman Pope, once. Compared to that, a woman king is nothing.'" |
| "decision/proposal/marriage/choice" | "'So,' you say. 'What do you think?' "Her pretty nose twitches again, which you are coming to recognize as a sign of hard mental labor. 'I think I see,' she says. [final decision]" | [final decision]" |
A plot manager (sometimes called a drama manager) is a piece of the program whose job it is to plan out events so that, whatever the player does, the story advances and an interesting narrative results. The plot manager might, for instance, decide that the player has wandered around for too many scenes without making any progress, and might compensate by making something happen that gives him a new hint on his current problem. It might trigger characters to act when it thinks the story should be reaching a crisis point. It might introduce new complications when it determines that the player is running out of problems to solve.
This is a theoretically challenging field. Sophisticated plot management requires that the story make difficult guesses, such as whether the player is "stuck" and what the player is working on right now. The advantage of using such a system is that (done very well) it makes the story extremely responsive to the player's behavior, which means that he is a real agent in the unwinding of the plot. It also contributes to the replayability, since trying the story a second or third time will produce quite different outcomes. But it is procedurally difficult to design a good plot management system and it requires a huge amount of content, as well: in order for the plot manager to give the player hints, change the course of events to suit his focus, and so on, the story has to have available many, many more scenes than will ever occur in any single playing.
Fate Steps In ★★★ is only a very brief sketch in this direction, one in which the "fate" entity is trying to accomplish an end goal and, every turn, looks for ways to push the story towards that conclusion, whatever the player does.
Goal-Seeking Characters for alternate ways to make characters act on their own.
One of the nice things about before rules for actions is that they allow us to express some planning for characters other than the player: we've already seen how this works, a bit. But we could also use before rules to write plans for an abstract story-driving entity, rather than for other individual characters. This story-driver could be in charge of all the non-player characters, as well as spontaneous or natural changes in the environment, shaping the narrative around the player's behavior.
The following example is a very simple one, but the same concept could be worked out in a great deal more complexity, with all sorts of alternative procedures available to our story-manager:
By default, Inform gives the player character (and every other person) a simple unitary body, one without hands or feet or any other defined parts. In many games this is adequate; but in others it is not enough, and we may want to endow all people with some more specific physical features, as in
Once we've done this, we may invite ambiguities if the player types LOOK AT FACE; it is this challenge that is addressed in The Night Before ★★★.
rBGH ★ gives the player a random height and then uses this to determine how the room should be described around him.
Slouching ★★ lets the player (and other characters as well) take different sitting, standing, and lying down positions.
As with ordinary numbers, we can choose random units when this is useful:
Suppose we want to let the player explicitly sit, stand, or lie down on different enterable objects. (Normally Inform treats all these actions as entering, but there may be cases where we want to distinguish between the player sitting on a chair and the player standing on it.)
Our implementation gives each kind of enterable a range of allowed postures, and one preferred posture. If the player enters the supporter or container without specifying a posture (as in ENTER CHAIR), he will be put in the preferred posture. If he explicitly says, e.g., STAND ON CHAIR, he will be put in the standing position as long as standing is a posture that suits the chair.
Suppose that we're going to give every person in the game a nose, but we want references to a nose always to mean the nose of someone *else*, if the player is with one other person. Moreover, on some occasions we're going to be in sight of Rudolph, so actions directed at an unspecified nose should always prefer his.
This relies on a somewhat advanced technique from the Understanding chapter, but since it may become useful with assemblies and body parts, it is worth mentioning here.
Next, we'll teach Inform some vocabulary to distinguish between the player and everyone else:
Here is the part that actually determines the preferences. "Does the player mean…" can result in five outcomes: "it is very unlikely", "it is unlikely", "it is possible" (the neutral default), "it is likely", and "it is very likely". This is discussed in greater detail in the Understanding chapter. Here, we want to discourage references to the player's own nose and encourage references to the nose of Rudolph, so:
And this part is just for decoration:
Some IF tries to make the viewpoint character more congenial to the player by allowing some customization.
Identity Theft ★ demonstrates asking the player to supply the viewpoint character's name.
Pink or Blue ★★★ demonstrates a way to let the player choose a gender at the start of play: this will mostly be interesting if the rest of the story makes some use of the player's choice. Since that example is written expressly to demonstrate included Inform 6 code, however, we may find it more congenial to generalize from the more flexible Baritone, Bass ★★★.
This is not the only way to go – as we'll see in the next section, there's also something to be said for making the viewpoint character a strongly distinct creature with well-defined preferences and attitudes.
Let's say we want to allow the player to enter any name he likes for his character. Moreover, we want to reject very long names (which are likely to be mistakes anyway), and we want to extract the player's chosen first name from the rest.
We also want to postpone the proper beginning of the game until we've gotten the name:
If we are compiling for Glulx, this is enough to capture not only the player's name but also the capitalization he uses.
If we are compiling for the Z-machine, the player's input will unfortunately be reduced to lower case before we can inspect it. If we would like by default to capitalize the first letter of each word of the name, we might substitute the following after reading a command rule:
The "reading a command" activity is rather advanced; for the moment, what we need to understand is that we're intervening in commands at the start of play and insisting that the player's first instruction to the game consist of a choice of gender. After that point, the gender will be set and play will proceed as normal.
In order to do the parsing, we define gender as a kind of value, and give several alternate names to each gender.
If we had a whole series of things to ask the player about, we might define a whole series of kinds of value
and use a "construction stage" variable to keep track of the current stage of character-construction, as in
Suppose we would like to allow the player to choose a gender for the main character. We'd also like this to happen at the beginning of the game and outside the main parsing sequence. "When play begins" seems like a good place to put this.
Now a piece of Inform 6 code handles the unusual input. It's not necessary to understand this to use it, and the code should work for any question you'd like to ask the player. The first three words in quotation marks ('male', 'M', 'man'…) correspond to positive feedback; the later three words correspond to negative feedback. So "to decide whether men win" will be true if the player types one of the first three, and false if he types one of the last three.
Much of the personality of the player character in IF emerges from what he can and cannot (or will and will not) do; part of the pleasure of playing a character arises from this opportunity for role-playing and role-exploration. Some characters are consciousless daredevils, willing to jump off cliffs, crawl through narrow gaps, and rob widows if the player commands it; others are repressed neurotics who barely dare to speak to other characters or touch anything that doesn't belong to them.
Finishing School ★ and Dearth and the Maiden ★ both treat the case of a character constrained by good manners and a sense of polite society: the former forbids only one action, while the latter condemns a whole range of them.
Constraining the character is only the half of it: we might also want to think about what sorts of unusual actions that character might be especially likely to take, and account for these. Of course, major actions that affect the story world will require some thought and implementation work, and we should consider carefully before making the player a character like, say, the Noble of Glamour, a spirit in human form who can charm all comers, transform bespectacled secretaries into divas, and cause spontaneous cloudbursts of scarlet glitter.
But even simple humans have some characteristic traits and gestures. We will probably want to write some characteristic reaction to EXAMINE ME, as demonstrated in Bad Hair Day ★. We might provide a few pieces of clothing or props that aren't strictly critical in the story, like a policeman's helmet or a feather boa:
We can liven up the interactive aspect of characterization if we give the player a little scope for role-playing: this may mean responding to gestures, like
(Of course, we would need to have hinted to the player that nail-biting is characteristic of his character.)
Clothing for more on dressing characters up.
Saying Complicated Things for conversation, another area in which the player character's personality might come into play.
It is often useful to write action rules which apply only when the player is observed by a third party. "In the presence of a person", however, will react even if only the player is in the room, because the player is, of course, a person as well.
A convenient way around this problem is to define an "other" adjective:
If we did not have "another" here, Inform would interpret even the player as a possible schoolmarm, leading to such lines as "yourself stares at you coldly…". Clearly not quite the thing.
85. ★ Bad Hair DayThe following example, indebted to the late Georgette Heyer, is suggestive:
In IF, as in all interactive storytelling, an essential problem is that the player does not begin the story knowing everything that the player character should, and so may implausibly bumble through situations that the player character should be quite comfortable in. If the player character has friends, an unusual job, a home or environment we're not familiar with, a secret past, these will all be a blank to the player.
Some games get around this by making the player character an amnesiac, or positioning him as a newcomer to a strange world in which his disorientation is explicable; but there are stories that cannot be told this way, and so we need other methods of getting the player to know what the player character already does.
Our first opportunity to inform the player about the player character is in the opening text of a story:
We may also want to write descriptions of objects to give extra background information the first time the player encounters them:
To expand on this, we could give the player a THINK ABOUT or REMEMBER command, with which he can call up information about people he meets or references he encounters in descriptions, so that he could (for instance) next type REMEMBER ELISE. Merlin ★ demonstrates one way to implement a character with memory; One of Those Mornings ★ puts a twist on this by letting the player FIND things which he knows his character possessed at some time before the story started.
| Topic | Response |
| "rain/weather" | "You've seen worse, but not often: it's falling so hard now that the tin rattles and the runoff, on the low side of the roof, would be a tenable source of hydroelectric power." |
| "hydroelectric power" or "power/hydroelectric" | "It's not as though you have any sort of light bulb in here to turn on, even if you could power it." |
| "light bulb" or "light/bulb" | "Light bulbs, like so much else, are a thing of your past. Or is it your future? Tricky, the way the world loops round on itself." |
| "past/time/future" | "Living backwards has its drawbacks. A tendency to confuse and annoy your friends, being one; the total inability to maintain a stable relationship; and a deep dissatisfaction with most of the bodily processes people enjoy, since they ultimately make you hungrier, colder, or-- no point dwelling on it, really." |
| "backwards" | "It's not even exactly *backwards*, now is it? It's more like a series of forwardses stuck back to back. As though someone had taken each track of a CD and put them in the exactly wrong order. You miss that. The music on demand." |
Suppose that, contrary to the usual rules of interactive fiction, we want to allow the player to discover the locations of things he hasn't actually seen yet:
The holder of the noun can be a room, a supporter, or a container: the phrase is not picky. We would want to be a little more careful if it were ever possible for an item to have been "removed from play" in our game, since then the holder could be nothing, and that would have odd results. In this particular example, though, that will not arise.
And that's it, as far as the find command goes. The rest is local color.
If we want to have the key found in different places when the game is replayed:
All of us carry around in our heads an (incomplete, imperfect) model of the world around us: an idea of where we left the keys, whether the oven is on or off, how many clean pairs of socks are left in the drawer, what we look like in our best pair of jeans. The differences between that mental model and reality are to some degree a reflection of personal character: our forgetfulness, our wishful thinking, our innocence or cynicism.
By default, Inform does not keep track of the player character's knowledge (or any other character's knowledge, for that matter) as a separate thing from the model world, relying on descriptive prose rather than modeling to introduce these quirks of characterization.
All the same, there are often times when we would like to keep track of discrepancies between the world model and the narrator's mental model. Perhaps the most common way to do this is simply to mark everything that the player encounters as "seen" when the player first examines it, thus:
or -- to have things remembered from the first moment they're mentioned in a room description:
The mental model need not always be accurate, of course. We might, for instance, have occasion to keep track of where the player character last saw something, even if the object has since been moved; or keep track of falsehoods the player character has been told in conversation; or make the player refer to a character as "the bearded man" until he is properly introduced.
Included with Inform is the extension Epistemology, by Eric Eve, which provides one way of tracking this kind of information. Epistemology distinguishes between items that the player character has seen, because they're objects in a room the player has been to, and items that are familiar to the player for other reasons, such as a quest item he knows about but hasn't found yet, or an abstract conversation topic. Anything that is either seen or familiar is counted as "known".
Modeling what the player does and does not know is only half the job, of course: we also need that information to affect the behavior of the story in plausible ways.
One obvious occasion to use player character knowledge is in the output of descriptions. We might want to respond to actions differently depending on what the player has previously done, as in Tense Boxing ★, or change the way we describe objects in light of new knowledge about them, as in Zero ★★★. Casino Banale ★★★ takes that idea much further, with a whole system of facts that can be narrated to the player in a somewhat flexible but interdependent order, as the player looks at relevant objects or notices them in room descriptions.
Along similar lines, we may want an object to change its name for the player depending on what the player knows. That name change should affect both what Inform displays and what it understands about the object. For instance:
Finally, the player's knowledge may affect how the story interprets commands, in the determining what is called "scope". When Inform tries to make sense of something the player has typed, it makes a list of everything that the player is allowed to refer to at the moment, and then checks whether all of the objects in the player's command refer to items in that list. Only things that are "in scope" are open for discussion.
If the player mentions an object that is not "in scope" -- say, a red hat left behind in the next room -- Inform will issue the response "You can't see any such thing." This is also Inform's reply if the player mentions a nonsense object ("EXAMINE FURSZWIGGLE") or an object that does not exist in the story world at all ("EXAMINE CELL PHONE" in a story set in Carolingian France).
This is not the only possible way for interactive fiction to handle such communication. Some games will respond differently to EXAMINE RED HAT and EXAMINE FURSZWIGGLE, saying in the first case something like "You can't see that now" and in the second "I don't know the word 'furszwiggle'."
The drawback of such behavior is that the player can make premature discoveries. If he hasn't found a sword yet, but thinks there may be a sword later in the story, he can type EXAMINE SWORD and see from the response whether his guess is correct. Nonetheless, there are people who prefer this alternative exactly because it does expose the limits of the story's understanding, preventing fruitless attempts to use a word that is not recognized at all. If it is desirable, there is an extension that will reproduce this behavior in Inform as well.
Using Inform's default behavior, however, scope is an ad-hoc way of keeping a list of things that are common knowledge between the story and the player. The player knows many things that the story might not (like what a cell phone is); the story knows a few things the player may not (like the fact that there is a sword in an as-yet unvisited room). Neither of those things can fruitfully enter into commands because they have no mutually agreed-upon referent.
By default, Inform assumes that "scope" includes only those things that are currently visible by line of sight. This works pretty well for a wide range of situations, but there are still plenty of occasions when we want to admit that the story and the player share a knowledge of things not seen. GO TO THE KITCHEN might be a useful command even when the player can't currently view the kitchen. ASK FRED ABOUT THE FOOTPRINTS should perhaps work even when the footprints are far away in the garden. SMELL STINKY CHEESE might need to work even when the cheese is invisibly locked away in a porous container but is exuding a stench. In a dark room, the player can't see his own inventory, but he should still remember that he's carrying it and be able to mention it. And sometimes we might want the story to acknowledge that the player is referring to an object that he has seen somewhere, even if that thing is now out of sight.
In practice, we have two ways to tinker with scope: we can change the scope for a specific command, using a token with any, as in
Or we can add areas and items to scope for all commands, as in
Puncak Jaya ★ demonstrates understanding references to characters who are currently off-stage.
Helping and Hinting for objects tagged with a "seen" property when the player first encounters them.
Getting Acquainted for a character whose name is changed during the course of play as the player gets to know him better.
Room Descriptions for more ways to change the description of a room depending on player experience.
Going, Pushing Things in Directions for ways to understand the names of distant rooms and move towards them.
Character Knowledge and Reasoning for models of knowledge for other characters than the player.
Sounds for ways of tracking audible objects separately from visible ones.
Lighting for ways to change what the player knows about and can manipulate in dark rooms.
Clocks and Scientific Instruments for a telescope that lets the player view objects in another location.
Continuous Spaces and The Outdoors for more on seeing into adjacent locations.
Here we have a box that prints out its current state and its history each time we open and close it:
Note that "was…" and "was not…" and so on may describe conditions more complicated than simple properties: we could equally well ask "if the box has been in the sack", "if the box had been carried by the player", and so on.
The past ("if the box was…") and past perfect ("if the box had been…") are especially useful for cases where we want to report on an action after the state of the item has changed; so, for instance:
This is in many respects similar to a rule beginning "After taking the mysterious box for the first time…", but it is superior in most circumstances, for two reasons.
First, it will respond correctly even if the player has somehow carried the box before without taking it explicitly: for instance, if another character gave him the box, if the box were moved into his inventory as a result of another action, or if the player carried the box at the start of play. Inform begins its reckoning of time when the game begins, so if the box is defined as being open at the outset, "if the box has been open" will always be true.
Second, "after taking… for the first time" fires only the first time the player attempts to take something. If the player tried to take the box, failed, and then tried again later, the "for the first time…" rule would not fire; our "if the box has not been carried…" rule would.
320. ★ Puncak JayaBy default, when something is not present, Inform does not allow a player to refer to it. But there are times when we might like to acknowledge that the thing mentioned in a command does exist somewhere in the game; it just happens not to be on hand right now.
One way to do this is to make an object that appears everywhere and responds to the name of its owner only when the owner itself is not in view.
We make the ghost a person rather than some other kind of thing so that it will be able to respond to commands such as KISS BOB or (even trickier) BOB, JUMP: if Inform did not recognize the ghost as an animate creature, it would not accept such input.
This is, technically, an assembly -- except instead of saying that every device has a button part, or that there are three daffodils in every garden room, the assembly is based on a non-physical relation that we just designed.
Based on the "representation" relation, we now devise a conditional relation that applies only when the represented thing is not itself in view:
Further complications of this example might require that the player meet a character before being able to refer to him or her.
148. ★★★ ZeroThe names of objects might want to change also:
This does require a rule for an activity (see the chapter on Activities), but it's a fairly straightforward one:
In a work of interactive fiction that involves many new discoveries, we might want to change the way we narrate room descriptions and describe objects as the player learns new information.
One approach to this is to create a model of the facts we want the player to find out, and attach some narrative text to each. When a fact becomes relevant to the story, that narrative text is shown to the player. So:
First we create the concept of facts, and the idea that facts can make some things more important than others.
Now, we also need a way to tell Inform to introduce certain new facts when the right previous ones have been introduced. We'll create a "following" relation, according to which a new fact can be told to the player when the player has already learned all the facts it follows. This way, we can simulate the effect of putting together several pieces of evidence to come to a conclusion:
Next we need a way for the game to introduce these new facts. Let's say we want them to come up when the player examines something appropriate, or sees it in the room:
The "after choosing notable locale objects" line here handles things so that any interesting conclusions we want to draw are always given first, followed by the less interesting description.
And finally, we need to give the player a little evidence to piece together:
Inform automatically creates a character for the player – a bland, personality-free entity at the outset, as we've seen. But there is no reason why the player need stick to this same identity throughout the story. Conventional fiction often jumps from one viewpoint character to another, and so can IF.
To do this at the most elementary level, we simply at some point
where Janine is a person we've already defined in the code. Now the player is in whatever location Janine inhabits, carries whatever Janine carries, and wears whatever Janine is wearing. Terror of the Sierra Madre ★★★ shows off this effect, and also demonstrates how to make the command prompt remind the player which character he currently controls. Some games instead give this information in the status line or after the name of the location when looking, producing output like
We could do the same by adding a line such as
Of course, we'll need a good deal of other work to make Janine a distinct person from whichever character the player was before. The distinction may come from changed capabilities of the new character, which we can express through new rules about actions; e.g.,
Janine may also have new, different perspective on her surroundings, expressed through the descriptions of the things she looks at; Uncommon Ground ★★ makes a "by viewpoint" token for text alternatives, allowing us to tag our descriptions to indicate which variations should be shown to which viewpoint characters. The Crane's Leg ★★★ and Crane's Leg 2 ★ offer more elaborate and specialized ways of customizing the player character's observations to depend on how he relates (physically and in attitude) to the things around him.
If we want to change the tense and person of narration from the conventional present second person, we may do this as well:
Though this only changes the form of the text produced automatically by Inform (responses such as "you can't go that way" might become, say, "I couldn't go that way"), and all author-written text in the story must be written in the tense and person intended.
Names of rules can be listed in tables. This is convenient if, for instance, we decide that we'd like to swap the rules we use for a specific purpose, as in this continuation of our earlier example of automated description:
| character | instructions |
| yourself | comparative observation rule |
| crane | bird observation rule |
A slightly more challenging case than the "by atmosphere" example is one in which we want to create text variations depending on the identity of our player character.
What we want to do is build a switch statement in I6, one that looks something like
out of I7 that looks like this:
Suppose we have an extremely detailed world model in which every object is characterized by many features -- in this example, material and height, though one could add more. Suppose further that we would like to generate descriptions of these things automatically for the most part, drawing the player's attention only to those aspects of the object that are particularly interesting.
So far, we have generally dealt with cases where the property of a thing can be a number (such as 3), a value (such as brightness), or a unit (like height, here). It is also possible for a thing to have a property which names another thing, as in "The mother of the baby trout is the large trout" -- where "mother" is a property, and its value, in the case of the baby trout, is large trout. We would define such a property with a line such as "A fish has a thing called the mother."
In practice, though, this is a bit confusing as syntax; moreover, Inform has a much more powerful construct for talking about the ways in which one object relates to another object. A full discussion of this will have to wait for the chapter on Relations. For now, it is enough to say that we can do this:
This will allow us to declare that some objects imitate other objects, like so:
Now each of these types has one ideal representative which has the fundamental attributes of its kind: the ordinary chair is the most chairlike chair imaginable, the ordinary table is the epitome of tableness, and so on. We are also allowed to refer to "the ideal of the chair", thanks to the way we defined imitation. (Again, the relations chapter offers a much more detailed explanation of how relations may be defined.)
So far the effect is not very deep, but we could take the auto-description a great deal further: providing a larger and more interesting set of variations; or writing a complicated set of rules such that the player only notices height variations when carrying a ruler; or switching between several player-characters, each of whom notices a different subset of characteristics. But these refinements would require more input from later chapters.
121. ★★★ Terror of the Sierra MadreSuppose we have a game where we want the player to control two different characters, swapping bodies from one turn to the next. First, the setting, and the two people who will alternately play:
If we tried the text above in Inform, we would find ourselves in the Hay-Strewn Corridor and confronted by both Teresa and Maleska. If "player" is not set to any named person, Inform creates a bland person called "yourself" to represent the player. To avoid this, we set "player" to the person we want to begin as. The player character is normally privately-named, so we'll need to make sure "Maleska" still means what it should.
Now the Corridor contains just two people, and we arrive on the scene as Maleska, with only Teresa facing us.
At the end of every turn we will use the 'now the player is…' phrase. (This looks as if it simply changes the value of "player": which it does, but it also carries out a complicated operation behind the scenes to effect the switch.)
Our two characters already see the Corridor differently, but let's differentiate them further:
In this small example, strength is not used for anything, except that we will display it on the status line:
That last rule doesn't quite do what we might have expected. When we print "[player]", we find that Inform usually prints "yourself". This is because Inform says "you" to mean Teresa when talking to the player-being-Teresa, and likewise for Maleska. We want to override that in this particular story, because the rapid switches of personality are otherwise hard to follow. So:
Quite a bit of interactive fiction design involves the creation of custom commands to expand on the library's existing set. There is more to know than we can review in this section; instead, this is to serve as an overview of the process, with hints about where in Writing with Inform we might find more technical details.
Before we even start to write our source text, we should think about the following things:
To take these one one by one:
(1) We may have a general idea of the phrasing we want the player to use -- say we want to add an SHOOT command which allows the player to fire a gun at something. (This is an intentionally tricky choice of verb, because it shows off so many possibilities.) So we might decide the base form of the action will be
So now we're going to need an action that applies to two objects -- the pistol as the noun, and Henry as the second noun. The problem is, though, that there are lots of other ways that the player could reasonably formulate the command, some of which leave out information:
To avoid frustrating the player, we should make a guess about what the player means whenever we're sure that guess will be reliable (we might, for instance, have only one gun in the story, so we know that SHOOT HENRY will always mean SHOOT HENRY WITH PISTOL), but ask the player for clarification whenever there might be ambiguity (SHOOT PISTOL gives no clue about the target, nor can we safely guess, so we want Inform to ask "What do you want to shoot the pistol at?"). The next section goes into more detail about how to handle these variations.
Conversely, there are cases where the player is offering too much information for the command we've defined – say we have a BURN command which doesn't look for a specified fire source, but the player is trying to BURN BOX WITH MATCH. We probably don't want to throw away the extraneous information as though it had never been typed, because the player might have typed something quite specific. BURN BOX WITH ACID, say, should not be cavalierly reinterpreted as BURN BOX (with a fire source). Instead, we want to give the player a bit of gentle guidance, perhaps using "Understand as a mistake", as in
Finally, there are some cases where we want to understand a phrase to mean a specific form of a more general action. For instance, we might want TURN DOWN THE MUSIC to mean the same thing as SET VOLUME KNOB TO 1. In this case, we may want to make a sort of dummy action which converts into the main action, as in
More about this can be found later in this chapter, under Remembering, Converting and Combining Actions.
Sometimes these kinds of details can be caught in play-testing, but it's a good idea to think about them specifically and in advance rather than leaving them to our beta-testers to sort out.
(2) To generalize very broadly, there are two possible kinds of command in IF: those that only exist to give the player new information (like EXAMINE, INVENTORY, LOOK, TASTE), and those that change the world model (like TAKE FISH, OPEN DOOR, UNLOCK GATE WITH BLUE KEY). The Inform library has some commands that really do none of these things by default – commands like JUMP that do nothing interesting at all most of the time – but those exist as hooks, in case there is ever something important for them to do.
Commands that ask for information are usually easier to implement. Very often we're looking to offer the player a new kind of information about specific objects, and these can be handled by adding new text properties, as in
Commands that affect the world model, on the other hand, can range from simple to very complex indeed. Sometimes we need to do nothing more than add an attribute to an object, like
so that our FOLD command can change the object into its folded form. At other times, we need quite intricate rules to account for a subtle multi-stage process – how fire is burning and spreading to objects, say, or how a conversation is progressing. Other parts of the Recipe Book offer solutions to some of these challenges.
(Strictly, we might count a third kind of command: the kind that controls the story itself. The Advanced Actions chapter discusses how to add actions out of world, as these are called, but the difficult ones are already built into Inform – saving, restoring, restarting, undoing a turn, and so on. Mostly when we need to add new actions out of world, they will be help or hint systems of some kind. More about these can be found in the Helping and Hinting section of the Recipe Book, under Out of World Actions and Effects.)
(3) Most commands that change the world require certain preconditions: the player needs to be holding the gun before he can fire it; the gun must be loaded with ammunition; if we're being especially detailed in our simulation, the safety must be off.
Often, there are also subtler details about how the command should interact with special items. For any new command we create, it's worth asking: should anything special happen if the player performs this action…
For instance, we might have written code so that if the gun is fired at anything but a person or a fragile object, the default response is "The bullet bounces harmlessly off [the second noun]." Our checklist would remind us to write special cases to prevent
and so on. Actions that destroy objects are especially tricky, because there are many things that aren't safe to destroy without carefully adjusting the world model. (What happens if we burn a door connecting two rooms? a wooden desk with a drawer containing an asbestos vest? the armchair Cousin Fred is sitting on?)
Once we've considered all the design issues pertaining to a new action, we're ready to start writing the source text. First we need to give the player a way to issue the command:
(Note how "it" stands in for the first item when we have an action requiring two objects.) The things that go in square brackets are called "tokens": they are blank spaces for the player to fill in with story objects. The different kinds of tokens are explained in the chapter on Understanding.
We can add synonyms with
and we can create reversed versions of commands with
These variations are also covered in the Understanding chapter. If the action needs to work on things that aren't within the player's sight or reach in the normal way, we may need to use an [any thing] token (see the Understanding chapter), as in
We may also need to modify reach or light levels (see Changing reachability and Changing visibility in the Advanced Actions chapter), or rely on the Deciding the scope of… activity.
As for guessing the player's intention when he isn't clear, we may want to consult the Does the player mean rules (to help Inform make guesses between multiple possible targets) and the activities Supplying a missing noun and Supplying a missing second noun (to help Inform guess an appropriate item when the player leaves something entirely out of his command). For instance, if the player typed SHOOT HENRY, it is the supplying a missing noun/second noun activity that would allow us to make Inform draw the obvious conclusion that he shoots Henry with the pistol in his hand. The Does the player mean rules are discussed in the chapter on Advanced Actions; the activities in the Activities chapter.
Next we need to define our new action, as in
In cases where we're using an "[any thing]" token to let the player affect objects that aren't normally visible or reachable, we'll need to define the action to apply to visible objects. This tells Inform that the player doesn't have to be able to touch the object for it to work. So for instance
For more on this topic, see Visible vs. touchable vs. carried in the Advanced Actions chapter.
The next step is to create rules for Inform to follow when the action happens. These can be check rules (which make sure that the conditions for the action to occur are fulfilled); carry out rules (which perform the action); and report rules (which describe the results of the action to the player). Any new action should have at least a report rule to let the player know what has happened (if anything), and a carry out rule if there are any ramifications for the world model. For instance:
It's important to remember that report rules may be describing something whose name is plural, such as papers or shoes, and write our text so that it sounds right either way; see the chapter on Adaptive Text and Responses.
More about defining actions and creating carry out and report rules may be found in the chapter on Advanced Actions.
Meanwhile, the check rules give us a chance to provide sensible restrictions on how the command works, as in
The chapter on Advanced Actions explains how check rules work. In the special case where we want the player to take things automatically before using them, we may want to define the action to work only on carried objects, as in
The activity Implicitly taking something (documented in the Activities chapter) allows us to modify what should happen during this process.
Lastly, a word or two about trouble-shooting. If a newly created command seems not to be working, we can discover what action Inform is really generating with the ACTIONS testing command, as in
If the desired command is not happening, we may need to review our understand lines. A common problem is that our new action conflicts with one already defined by default. In that case, we may want to check the Actions index and see whether there are already-defined actions which might conflict with it. If so, we may need to redefine a command with a line like
If that's not enough, we can get a comprehensive view of everything that happens during an action with RULES: this will list all the check, carry out, and report rules that Inform is using to perform the command.
Memory and Knowledge for more about the any token and the concept of scope to control what the player may refer to in a command.
Much of the rest of this chapter discusses the behavior of specific commands in Inform's command library, and how we might change and build on these. This section is instead an overview of the general principles: where and how can one intervene?
Whenever we are dealing with actions, the Actions Index is likely to be useful: it lists all the actions currently implemented, whether in our own source or in extensions or the Standard Rules, and lists the rules pertaining to each.
The lightest and easiest way to change behavior is with an Instead rule:
The addition of "rule succeeds" tells Inform that the instead action was a success rather than a failure; this is not usually very important with the player's own actions, but can be useful for actions performed by other characters, so that a successfully replaced action is not followed by the disconcerting line
Before and After offer alternative easy forms of modification; the Basic Actions chapter explains all three.
Changing the way an action works in all cases is usually better addressed by changing the main rulebook, rather than with one (or many) instead rules. We may add new check, carry out, and report rules to existing action rulebooks. The Advanced Actions chapter describes these, and ends with some guidelines on when to use before, instead, and after, and when to use check, carry out, and report.
Similarly, we may delete, move, or replace rules that are already present (see the chapter on Rulebooks). This is handy if we decide that an action has restrictions that we dislike and want to abolish. If the restriction we need to change is part of the accessibility rules – those which check whether the player can take, see, and touch items – we may need to look at Changing reachability or Changing visibility in the Advanced Actions chapter (to revise what is allowed), at Deciding the scope of something in the Activities chapter (to influence what can be seen when).
If, for instance, the player character is a burly fellow who can lift any other character he likes:
…and rip knobs off doors:
…and commit petty theft:
The right approach to use also depends a bit on how systematic a change we anticipate. We may find that instead rules become cumbersome when we want to specify behavior for a very large number of objects. It's fine to have
but a bit more tedious to have to write
in a story in which most items have unique flavor descriptions. In that situation, it may be more sensible to overhaul the design of the action: create a new text property for things, and revise "tasting" so that it now consults this property:
Finally and most sweepingly, we can rip out whole passages of the Standard Rules and replace them – or not. This is a drastic measure and rarely necessary (or so we hope); but see the Extensions chapter for ways to replace sections of existing source, or even revise the Inform 6 template files on which Inform depends. By these means almost anything can be changed. We can throw out a whole range of existing commands and start from scratch, for instance, if we want Inform to know about a completely new and different command set.
Magic (Breaking the Laws of Physics) for a hat that lets the player walk through closed doors, and an NPC able to reach through solid containers.
Under most circumstances, locking and unlocking require the player to be carrying the key he uses to unlock something. This makes sense -- unless the key is on a keychain, or on a chain around his neck, for instance. So here we explore one way to circumstantially override the carrying requirements, while still making sure that the player cannot unlock the door if the unlocking tool is nowhere in sight.
In essence, we are rewriting the carrying requirements rule with a different one of our own devising, and swapping it in only at those moments when it is correct to do so.
We can now replace the usual behavior of the carrying requirements rule (to check whether the player is carrying something and, if not, to generate an implicit take) with a similar rule of our own; note that "if the player has the second noun" is a more compact way to write "if the player carries the second noun or the player wears the second noun":
For a more systematic handling of the keychain problem (and a number of other refinements to the behavior of doors), see the Locksmith extension included with Inform.
Looking is quite a complicated command, since the production of a room description takes many steps. A detailed description of this process may be found in the Room Descriptions section.
By convention, a player sees full descriptions of rooms he enters more than once, but may type BRIEF in order to see shorter descriptions, and SUPERBRIEF tells the story never to print room descriptions at all. VERBOSE restores the default behavior.
These conventions are not always appropriate, however, especially in works where experiencing a changing environment is essential. The use option
changes the default behavior so that rooms are not always described fully to the player. Verbosity ★ demonstrates how this works.
The player always has the option of turning room descriptions to BRIEF or SUPERBRIEF mode. Verbosity 2 ★ demonstrates how we might remove the player's ability to change the default behavior.
Room Descriptions for a detailed description of how Inform creates room descriptions and how to change the results.
Going, Pushing Things in Directions for ways to change just those room descriptions that are shown as the result of the player's movement.
Memory and Knowledge for ways to change the room description in response to the player character's knowledge at any given stage of play.
By default, the description of a room is printed every time the player enters a room.
On a device with very limited screen space, however, we might wish to supplant that behavior with "brief" descriptions. In Brief mode, Inform prints room descriptions only when the player enters that room for the first time. Afterwards, the text is skipped, for brevity, though the player can see it again at any time by typing LOOK.
As we saw in the previous chapter, we can set "use options" to control certain aspects of the player's experience. One of the use options is the option to
which changes the defaults so that the description of a room is printed only the first time the player enters.
If we type "test me" during play, these commands will be carried out automatically, and we can see that when we return to the Research Wing, the description is not given a second time.
Some notes: the player can also turn full-length descriptions on or off with the commands "verbose" and "brief", or set a minimal-description setting with the command "superbrief". This power still belongs to the player even if we have set the use option to show brief room descriptions by default.
Moreover, we can ourselves check what the state of the descriptions is, with
Finally, it is possible to exercise more precise control over what the player sees on his first and subsequent visits to a room; see the next example for details.
395. ★ Verbosity 2Suppose that we want the player always to see full room descriptions, even if he tries to reset the defaults -- perhaps because there is vital information there which he will miss if he turns off full-length room descriptions.
To do this, we might want to remove the standard behavior of the three actions associated with BRIEF, SUPERBRIEF, and VERBOSE, replacing them with explanatory messages about how the game behaves. We cannot use Instead to override these actions, because Instead rules do not apply to actions out of world. Instead, we will want to remove and replace the carry out rules.
We can do this easily by going to the Actions Index, looking up the detail panel for, say, "preferring abbreviated room descriptions", and click the "unlist" button to paste in the sentence that will remove this rule from the rulebook.
Let's remove all three of the carry out rules and substitute our own:
By default, examining an object shows its description, and – for devices – tells us whether the object is switched on or switched off.
This kind of additional information is not always what we want, so if we have a device whose on/off status we want to conceal, we may write
On the other hand, there are times when we may want to add a similar line or two to the descriptions of other kinds of objects. Crusoe ★★★ allows us to append an "It is charred." sentence to the end of descriptions of things we have burned in the fire. Since it works by introducing a "printing the description" activity, Crusoe is also a good example to start from if we want to introduce more complex, flexible descriptions of items throughout our story.
Odin ★ rewrites the "You see nothing special…" line with other text of our own, for items that otherwise do not have a description.
Finally, we may want to look at multiple things at once. The Left Hand of Autumn ★★★ demonstrates how we might provide a different response for EXAMINE PAINTINGS than for examining each individually; Beekeeper's Apprentice ★★ provides a SEARCH command that will show the descriptions of all the scenery in the current location.
Actions on Multiple Objects for an alternative EXAMINE ALL command.
In recent years there has been a strong trend towards providing unique descriptions for all implemented objects. Often this is a good idea, but there are also contexts in which we may want to discourage the player from looking too closely at some things and concentrate his attention on just a few interesting ones.
The trick here is that leaving items completely undescribed leads to rather dull exchanges like this:
…which can leave the player with the impression that the author was simply too lazy to describe everything. So it can be a good idea to replace that default message with a different one more appropriate to the game. For instance:
Because the description is attached to a whole kind ("thing"), it is really a blanket instruction about many objects at once. More specific instructions always override less specific ones, so we can easily make exceptions. For instance, the following will work correctly:
We have to create a suitable action and say what it does, and to repeat what we do through all the scenery items. That needs material from subsequent chapters, but is quite ordinary Inform all the same:
The reason for this example is to show the use of saying "[run paragraph on]". It means we have output such as:
Without the running on, the prompts "hive:" and "honey:" would be separated from the descriptions following them, which would look a little odd.
295. ★★★ The Left Hand of AutumnSuppose that we have a game in which groups of objects can have meaning apart from their individual significance -- perhaps there are spells that can only be cast by collecting just the right items in the same place.
In this case, one of the things the player might like to be able to do is look at several items together and get a special response, different from looking at the items individually.
To make this happen, we need to do several things:
Now for step 2, overriding Inform's usual output of names of objects:
We'll save our "to describe" phrase until Section 2, when we can give the game specific instructions about how to report different lists of objects.
Now, the player might also want to be able to refer to a group of item by some kind of group name, so let's add the option of creating a Table of Collective Names which will interpret these:
And as a bit of polish, because we'd like SEARCH TABLE to have the same effect as EXAMINE ALL ON TABLE:
Now we define a few actual lists of items:
We sort the lists so that regardless of how we change the rest of the code (and the order in which objects are coded), the resulting list will always be in sorted order and ready to compare with the list of items the player wants to look at. And thanks to the "Reading a command" code we wrote earlier, we can also teach the game to understand the player's references to "the left hand of autumn" as a specific collection of items.
| name-text | relevant list |
| "left hand of autumn" | "[arcane list]" |
| "gloves" | "[glove list]" |
| "pair of gloves" | "[glove list]" |
Suppose we want to add rules so that any time we examine a charred object (and most of our objects can be charred), a line about the charring is appended to the end of the object description. We could use "after examining…", but perhaps we would prefer for the sentence about the charring not to appear in its own paragraph.
This is an ideal occasion for a new activity. We look at the action index for "examining" to identify the rule that causes the old behavior (in this case, the "standard examining rule"); replace this with a new rule that calls our activity; and write our "printing the description" activity in such a way that it uses an object's description without forcing a paragraph return afterward.
Then we will use "after printing the description" to add our line about charring, and make sure that the paragraph return does occur before the prompt.
So:
This instruction replaces a normal piece of the examine action, the standard examining rule, with another one of our own devising. (The replacement of the standard examining rule will be explained in more detail in the chapter on rulebooks.)
All we have done here is enclose what is usually just a rule inside an activity. This means that we can now write before and after rules for the activity, and also add special instructions like "Rule for printing the name of something while printing the description of something" -- this may not be likely to arise often, but Inform now has the concept of "printing the description of something" as a separate context of action. Next we add the modification that lets us append to the description without a new line:
"run paragraph on" here will mean that we do not get a paragraph break following the description, even if it ends with a period. We also insert a space, so that our follow-on comments will be properly punctuated.
The instead at the end of this line stops Inform for going on with any other "after printing the description of…" rules.
The standard library also has rules for printing additional text about containers and supporters with visible contents, and devices that are switched on; with this current system, we could add those as "after printing the description" rules as well, building up a complete paragraph if we wanted. But for simplicity we won't exemplify all of that here. The effects would be much the same as with the "charred" line.
Now, because we want to make sure that we always do get a paragraph break after our description, we add this rule last after all the other rules. "Last" and "first" rules are covered in more detail in the chapter on rulebooks.
The player's description is handled in an unusual way, and this will produce a space paragraph break there where it should not. Instead, therefore, we will add an instead for examining the player (probably a good idea anyway):
The "printing a description" activity may be useful for other games, and can be imported just by lifting section 1.
Finding hidden objects is a classic puzzle in IF. Beachfront ★ provides the most basic example, an object that becomes visible only when we have searched the papers on a cluttered desk. Beneath the Surface ★ takes this further, giving all large furnishings the ability to conceal items, and allowing the player to put things underneath other things, as well as find them. Flashlight ★ adds an extra twist to the puzzle by requiring that the player have a flashlight to shine under a bulky object in order to find what lies underneath.
Looking inside an object is generally handled by the searching action, and we could extend that to allow the player to search multiple or complex objects. Matreshka ★ turns the puzzle on its head by allowing the player to search a whole room systematically with only a single command.
Kitchen and Bathroom for the related case of needing to look in a mirror.
Suppose we have our player, a detective, searching for evidence; we don't want him to be able to use this evidence until he has performed the action that reveals it, but after that it should be visible in the room when he looks.
A simple way to do this is to start the object -- an envelope, in this scenario -- out of play, and only move it into the location when the player looks for it:
Here we've changed the property of the envelope to keep track of the fact that it has been found, so that if the player tries again, he won't find anything more.
Notice that we have two rules that apply to "searching the desk", but one of them has a more specific set of parameters ("when the envelope is lost"). This means that Inform will consult that rule first and use it if it applies; it will only carry out our plain vanilla "instead of searching the desk" rule when the more restricted rule is not relevant.
And now we need to borrow from a later chapter for the command that will make this work:
Because visibility is checked before instead rules, this discovery will (correctly) occur only when the player does have enough light.
233. ★ Beneath the SurfaceThe standard world model provides for the idea of containers and supporters, but this is not the only way that objects can relate to one another in the real world. Here we try adding the idea of concealment beneath another object:
Occasionally we would like to change the way the name of something is printed as part of our inventory, and we can do this with a printing the name rule such as
There are also several possibilities for redesigning the inventory list as a whole. Persephone ★★★ shows how to divide an inventory list into two parts, a "You are carrying: " section and a "You are wearing: " section. Equipment List ★★ goes further, and shows how we might use Inform's specialized listing functions to create a variety of differently formatted inventories.
Sometimes the way Inform by default lists properties such as "(closed)" or "(open but empty)" isn't quite what we want. Oyster Wide Shut ★ offers a flexible alternative to the standard behavior, allowing finer control over which properties are listed and how they are described.
Trying Taking Manhattan ★★★ replaces the inventory behavior for other characters: instead of silently looking through their possessions (but not describing them to the player), they now describe to the player what they're carrying and wearing.
As we've seen in earlier examples such as "Equipment List", it is possible to vary the way Inform creates inventory listings in general (to create lists that look more like paragraphs of prose, lists divided between what the player is wearing and what he isn't, and so on). We can also use activities to alter the printing of specific objects' names and contents, as with the "omit contents in listing" feature after printing the name of something.
We may find, however, that we would like a great deal more control over Inform's printing of inventory details, not just as a special effect for a few items, but throughout the game.
We start by turning off Inform's native property writer:
This is very much like the library's standard behavior, but with the exception that "giving inventory information" or even "giving brief inventory information" are omitted. Here's how we supplant it:
Now, our property-aggregation rulebook is going to look at a given object and decide on a list of features that should be mentioned in inventory. We'll start by producing something quite similar to Inform's default behavior:
Notice that we don't need to write any rules about how to print that list of text: because Inform is printing out a list, it will automatically insert commas, spaces, and the word "and" where appropriate; and it will automatically follow the "use serial comma" option, if we have it set.
Now we're free to meddle. Let's give the player a bunch of possessions that will be listed in interesting ways in inventory:
Now suppose that we don't want the oyster to say "closed" when it's closed. Instead, we'd like it to say "clamped shut". As this is the only property the oyster will ever have, we can simply override his whole property-aggregation rulebook:
That's fine for the oyster because "clamped shut" is the only property he'll ever have. What if we'd like instead just to revise the way the sack (and only the sack) gets described as providing light?
Now the flashlight (and any other regular light sources we might add to the game) will be described as "providing light", but the sack will only be said to be gently glowing -- a bit more appropriate for its rather fainter gleam.
We might also wish to add a systematic feature across the board to include a new property in the inventory list? Let's say the player can enchant his possessions, and enchanted possessions should thereafter be listed accordingly:
Further variations are possible as well: if we used a "before printing the name…" rather than an "after printing the name…" rule, we could automatically generate lines like "an open and empty phosphorescent plastic sack", removing some of the artificiality of the parentheses.
Or we could add more logic to the rules about which properties are mentioned, so that some features of objects were mentioned in inventory only if the player was wearing the correct detection device, like so:
Most of the phrase options above are relatively self-explanatory; a few are less so. Here is an overview:
"With newlines" tells Inform to put a new line before each listed object. Indented tells it to indent contents of objects, when listing these.
"Giving inventory information" means to append information such as (closed) or (being worn) to objects.
"As a sentence" means to put "and" before the last object and commas between them; this is usually not used in conjunction with newline listing. "As a sentence" obeys whatever conventions about the use of the serial comma we may have established with the "Use serial comma" option.
"Including contents" means to list the contents of open or transparent containers and all supporters, whereas including all contents means to list the contents of all containers, even opaque closed ones.
"Tersely", perhaps unexpectedly, puts parentheses around objects listed as the contents of other objects.
"Giving brief inventory information" omits most of the inventory tags, such as "(open)" and "(worn)", but does list "(closed)" for closed containers which might not otherwise be obviously openable.
"Using the definite article" means prefixing objects with "the", if applicable, rather than "a".
"Listing marked items only" means including only objects that have already been declared "marked for listing".
"Prefacing with is-are" means that Inform will write "is" before the list if it contains only one item, and "are" if the list contains more than one.
"Not listing concealed items" means to omit from the list anything which is scenery.
Finally, "with extra indentation" means that the whole list should be indented slightly, in emulation of the default inventory listing.
With this information, we can try rewriting the inventory behavior to emulate the standard or to explore alternate versions:
We begin by emulating the standard inventory listing style:
Here we offer the alternative of listing everything together as a paragraph:
This may be unsatisfactory, however. Items that are inside other items are not set off from those merely carried by the player. One way around this is to use terse listing, giving such descriptions as "a waterproof sack (in which are an undersea map, a diving guide, a cup (in which is a worm) and a 500 Argentine pesos)" as opposed to the more confusing " a waterproof sack (open), inside which are an undersea map, a diving guide, a cup, inside which is a worm and a 500 Argentine pesos".
If, using the above style, we close the sack, we will still get "(closed)" after the sack's listing. The following minimalist listing style abolishes even that nicety:
If we want to list worn things separately from carried things, we have occasion to put "listing marked items only" to work:
And similarly for a tall divided inventory:
If we wanted, we might replace the rule for taking inventory as follows:
Inform has built-in commands for other people, and sometimes we may want to adjust the way these work without completely disabling and replacing the command. Suppose, for instance, that instead of
we'd like someone taking inventory to report what he's got, thus:
To do this, we could replace the built-in report rule with a different one.
We may want to change the default refusal message when the player tries to pick up scenery: Replanting ★ demonstrates this case simply.
Removal ★ modifies responses to successful TAKE commands, with the effect that when the player picks up an item, he gets a response such as "You take the book from the shelf."
Croft ★★★ modifies the DROP command, so that objects dropped on specific surfaces get reported in a special way. Celadon ★ allows the player to drop even objects he is carrying indirectly, for instance on a tray or in a sack.
Morning After ★ introduces a simple rule that changes the behavior of the whole story: whenever the player takes an item he hasn't already looked at, he automatically examines it. This picks up the pace of exploration passages where the player is likely to be collecting a large number of objects.
By default, when the player tries to put or insert an item that he isn't holding, Inform prints a refusal message; Democratic Process ★★★ and Sand ★★★★ offer ways instead to have the player first pick up the relevant items. (The former applies to single items the player is trying to place; the latter expands coverage to work even if the player uses a command affecting multiple objects.)
Taking also happens as a result of other commands. Such takes can be made unnecessary by turning off the "carrying requirements rule" under particular circumstances, or presented differently using the implicitly taking activity.
By default, "TAKE OAK" in the example above will produce the response "That's hardly portable." This is fine under many circumstances, but also a bit generic, so we might want to override it for a specific game.
Here we've used an "instead" rule; we will learn more about these in the section on actions. This allows us to define our own results for taking an object.
Note: "scenery" is a property of an object (about which we will hear more later). So when we use it in rules, we can talk about "some scenery", "something that is scenery", or even "a scenery thing" -- the last one doesn't sound much like English, but is a more plausible construction with other adjectives.
90. ★ Morning AfterSuppose we want to make the player's life slightly easier by examining everything he picks up, if he hasn't already examined it.
Carry out rules are explained in more detail in the chapter on advanced action handling. For now, it may be enough to know that what we put into this carry out rule for examining will happen any time anything is examined, but that it will not interfere with the rest of the predefined behavior of the action. The player will still see the object description and so on, as usual.
Suppose that we want to change the reporting of "take" so that the player is always told something like "You take the book from the shelf." or "You pick up the toy from the ground." In order to generate these reports, we will need to know where the object started, even though by the time we are printing the output, the object will have moved.
The previous locale could in theory be either a thing or a room, so we make it "an object" -- that is, the most generic possible kind, to which both things and rooms belong. Now we record what the previous locale is at the beginning of each taking action:
By default, Inform only lets the player drop those things which he is carrying -- that is, those directly in his possession. Things inside satchels or on portable trays have to be taken first.
If we want to change this behavior, we might add a dropping rule that distinguishes between carrying and mere enclosure (introduced back in "The location of something" in the chapter on Things):
"Stop" and "Continue" are most useful when we need to write rules that will have to stop the action some of the time but at other times let it pass; so for instance:
Suppose that we have a design in which the player spends lots of time on enterable supporters, and in which we want to report certain actions -- dropping things onto those supporters, or leaping from one to another -- in a new way. We might begin by adding some action variables to help us keep track of the situation:
Because this rule occurs before the "implicitly pass through other barriers rule", that rule will not occur when we move from platform to platform; we'll use our own custom rule instead.
As mentioned in this section, the "implicitly taking" activity does not allow us to skip an implicit take entirely. In order to do this, we need to borrow from the chapter on Rulebooks and tell Inform that one of the rules normally built in to the Standard Rules does nothing in certain circumstances:
Note that because we only deactivate the carrying requirements rule for showing purposes, the player still takes the gumdrop before eating it.
87. ★★★★ SandThe above example does not quite work when we want the player to be allowed to take multiple objects at once before putting them somewhere: we also need to add a couple of "understand" rules borrowed from many chapters later. While the reasons may not be immediately clear, we include the demonstration here for the sake of thoroughness:
Going is the most complex of actions after looking (or perhaps including looking): the success of every movement depends on the direction the player goes; the room he starts from; the room he intends to reach; whether there are any doors intervening (and, if so, whether these are closed or locked); whether he is traveling by vehicle; and whether he is pushing anything in front of him. When he gets there, the description he sees is itself generated by a looking command.
Pushing something in a direction is really a sort of going. The command >PUSH WHEELBARROW WEST first checks certain qualifying rules: by default, only things defined as pushable between rooms may be pushed, and they may be pushed only in horizontal directions (not UP or DOWN) -- though these rules can be overridden, as we see in Zorb ★★★. If the player's pushing attempt passes these criteria, the action is translated automatically into a going action, with all the usual checks about whether that direction leads anywhere, whether a door is in the way, and so on. The converted action afterward can be caught with such rules as
Since the two actions are internally being handled as one, both are discussed here.
It is very common for players to make a mistake and type the wrong direction command, or even to misunderstand the room description and not recognize all the possible exits. Bumping into Walls ★★★ helpfully adds a facility so that when the player tries to go in the wrong direction, the story lists the correct possibilities, as in
Assuming that travel succeeds, another useful technique is to provide some sense of the journey between locations, especially if they are remote from one another or the player has to do something unusual to get from one to the other. Up and Up ★★ adds a short description of travel when we approach a new room, before the room description is printed; Veronica ★, conversely, adds a comment when the player leaves a region of the map. The Second Oldest Problem ★ intervenes and kills a player who tries to travel from one dark room to another. Mattress King ★ embellishes the description that automatically results from PUSH MATTRESS WEST, adding a line that describes the player pushing the object before describing the new room approached.
We may also want to add a brief comment when we arrive in a new room, after the room description is printed. One trivial way to do this is to append the line to the room's main description, conditionally, like this:
But often we want our first-glance comment to come after some items in the room are described; and for this effect, we would use the "first look rule" defined in Saint Eligius ★.
If these methods are not enough, the looking action has an action-specific variable called "the room-describing action", which records whether this particular instance of looking comes about because the player typed LOOK or because the player traveled to a new location. We can consult this variable if we want to make looking work differently after going, as for instance here:
Another category of examples treat how we handle the movement commands themselves. The eight compass directions, with UP and DOWN, IN and OUT, are used as standard in most interactive fiction, but they are not the only possible way of navigating, and strike many newcomers to the genre as counter-intuitive, since when strolling around in real life most of us rarely think about our travel in terms of compass orientation. Misadventure ★ allows the player to GO TO a named room, instead, and calculates the best route to reach the destination; Safari Guide ★★ builds on this by letting the player make the whole trip in a single move, automatically opening any doors that stand in his way en route.
In the same spirit of interpreting the player's intentions sensibly, Provenance Unknown ★★★ modifies the pushing command so that if the player pushes the top object in a stack of objects towards a direction, Inform attempts to move the bottom item instead. This is convenient if, for instance, we have a heavy television on a movable cart and want PUSH TELEVISION WEST to work just as well as PUSH CART WEST.
We also sometimes want to respond sensibly to terse movement commands or ones that rely on some knowledge of where the player has already been. Polarity ★★★ provides a GO BACK command, allowing the player to retreat in the direction from which he came, while Minimal Movement ★ understands LEAVE, GO, and so on as OUT, in the absence of other information. Owen's Law ★★★ takes this further, calculating from the best routes on a map how to make OUT mean "move towards the exit of this indoor room", and IN mean "proceed further into the interior". Wonderland ★★ assigns altitudes to all rooms and works out the local best meaning of UP and DOWN accordingly.
Map for how to create other kinds of new direction.
Varying What Is Read for further divisions of the standard compass, such as north-northwest.
Ships, Trains and Elevators for ship-board directions.
Bicycles, Cars and Boats for common vehicles in which to travel the map.
Suppose that we want to have something happen when the player leaves a region we've defined. "Instead of going from (the region)…" will not suffice for this, because this rule will be invoked every time the player successfully leaves a room within the region, whether or not he is going to a room that is also in the same region.
Instead we need a rule that is a bit more specific, like this:
By default, when the player pushes something a direction, Inform checks to make sure that the object is pushable between rooms. If not, it blocks the action; if so, it carries out a normal going action with the pushed object taken along.
Also by default, this action produces only a description of the new room that we've traveled into. But suppose we would like to print a short message describing the pushing action first:
Text in this example is drawn from Will Crowther's original 1976 FORTRAN implementation of ADVENTURE, the founding work of the genre, whose source code was rediscovered by Dennis G. Jerz in 2007. Note the capitals: the program ran on an early computer without lower case lettering. They look a little mimsy now, but picture them glowing green on an old-style cathode ray tube monitor in a darkened room late at night.
The problem alluded to is that the player is forbidden to walk between two dark rooms, so that he must always have light to see by from at least one end of any movement. Writing source text to achieve this is tricky to get right in every case, because the determination of light is hard to do. Here we interleave the necessary rules into the existing "going" action, using a new action variable to record the number of ends which are dark as experienced by the player, which might be 0, 1 or 2:
And now three early rooms to try this out.
This is only the second oldest problem in the IF literature: the earliest puzzle is unlocking the steel grate which bars entrance to the cave.
306. ★ MisadventureThe original Adventure allowed the player to type the names of rooms in order to move to them, and it is now not too difficult for us to do the same. Adventure restricted this option to adjacent rooms, but we might want to be a bit more flexible, so we will accept any room:
We should reject movement to the player's current location, or to anywhere he hasn't been and can't see:
The assumption here is that the player does know the names of the rooms adjacent to his current location, even if he hasn't been there yet.
Now for the travel itself. The simplest way to ensure that the usual movement rules will still apply is to convert GO BY NAME into a GO action, and here the best route comes to our aid:
This will allow the player to travel toward rooms he has already visited even if they are several moves away.
Finally, so that the player can also use the names of doors as commands:
And in keeping with the original, we might add to our scenario a rule or two about restrictions on movement, just to test that it's all working right:
Sometimes it would be nice to respond a little more sensitively to a vague command such as "leave" -- converting it, perhaps, to a "go out" command.
This particular situation is very slightly complicated by the existing rules about vague movement, but fortunately we can easily turn those off.
A not-infrequent desire in IF is to provide a few lines of comment when the player first enters a new room, after the objects are described but before anything else (such as an every turn rule) can fire. The cleanest, most systematic solution is to add a rule to the carry out looking rulebook, so:
And now the scene itself:
Sometimes when a player moves from one room to another, we want to imply that a considerable amount of time elapses, or that something interesting occurs on the way. In that case, we might want to print more than just the room description itself. Here is how we might define a couple of rooms that are far apart:
And now we borrow from the instructions on Actions to create our actual message. "Before…" introduces a rule that occurs when the player tries to do something; in this case, we will make a Before rule for going to the tower.
Suppose we have a landscape with a great deal of up and down variation, where GO UP and GO DOWN will be significant almost everywhere, and specifying them all individually a tremendous pain:
Since Mount Rainier National Park runs to over 235,000 acres, we will omit the rest of the locations, but it does seem fair to give a little more credit to anyone who makes the summit:
The foregoing example moves the player one location towards his destination, and requires that rooms have been visited before. But suppose we wanted to be a bit more lenient about movement, and let the player make as many steps as necessary per turn. We will also show consideration about doors, using the "Locksmith" extension supplied with Inform. (Now every time the code attempts opening a door, unlocking rules will also be invoked.)
Notice that we continue the movement until one of two things happens: either the player reaches the room that is his destination, or the going attempt doesn't work. In the latter case we stop the action in order to avoid hanging the game up in a loop. This event might occur when the player runs into a locked door, for instance.
102. ★★★ Bumping into WallsFirst we add an instruction to determine which ways lead to other rooms.
Now we build in the instruction for what Inform should say if the player tries to head in a direction that leads nowhere:
There is no theoretical reason why we have to define "count of exits" here: we could, if we wanted, just say "if the number of viable directions is 0", "if the number of viable directions is 1", and so on. However, each calculation of a "viable direction" takes a bit of computing power, so there is some slight savings in not requiring the game to count viable directions more than once in this routine.
The main trick of this is always to record where the player has gone when he has just moved.
Here we record where the player has been before moving him; by calling this the "first carry out going rule", we make sure that this rule is followed during the going action before any other pieces of the movement occur. For more detail, see the chapters on advanced actions and on rules.
And to deal with the case where the player has not yet moved:
Suppose we have a series of items that might be stacked on top of one another -- say a heavy television on a rolling cart, and we want the player to be able to move the cart with PUSH TELEVISION EAST just as well as with PUSH CART EAST.
This takes a little redirection, using a setting action variables rule. This is not a kind of rule we've encountered yet, and in fact we won't meet it until the Advanced Actions chapter; it is included here for the convenience of authors who want to modify the effect of pushing without reading that far ahead:
This rule says that any time we push an object that is on top of a stack of pushable objects, we should transfer the action to the item at the bottom of the stack.
The rest is merely a test case.
There are two aspects of Inform's handling of pushable objects that are particularly prime for modification. One is that we may want to change the language used to refuse the pushing of unpushable objects.
Second, Inform by default assumes that it is impossible to push objects in up or down directions. This makes lots of sense if the player is trying to push a wheelbarrow up a ladder; it makes less sense if instead we're pushing a ball up a slope.
We solve both problems with some syntax borrowed from the chapter on rulebooks: in the first case, we replace the old rule with a new one with more friendly phrasing; in the second, we remove the rule entirely. More about how to do this is described in the rulebooks chapter; and in general we can find out what rules contribute to any given action by looking at the Actions index. In this case, the action is "pushing it to", which has its own set of prerequisites (called check rules) that make sure the object can safely be pushed, before turning processing over to the going action.
And now to provide a scenario where the player can push something up and down a hillside. Most of the rest of the example is there for local color and to provide a way to demonstrate these rule adjustments:
Suppose we want the game to interpret "GO OUT" as "move towards an outdoors room, or towards a room with more exits than the current room", while "GO IN" means "move toward a room with fewer exits, or towards an indoors room". Thus going in repeatedly within a building would lead towards dead-ends, while going out repeatedly would lead towards the center of the building and then towards an exit to the outside world.
We start by encoding these rules as definitions:
| let the way be the best route from the location to | the destination; |
This "listing available exits" is a refinement borrowed from a future chapter, which allows us to specify special listing and printing rules:
Under ordinary circumstances, Inform does not keep track of the player's posture, nor of his exact location in a room. Lies ★ implements a room in which the player can lie in different positions on the floor, getting different views as a result.
Our other examples are all modifications of the way Inform handles player movement to make better default guesses at what he wants to do: Anchorite ★ adds a GET DOWN and DOWN command that work when the player is on a supporter, to accompany GET UP, GET OFF, and GET OUT (already understood). Get Axe ★ makes the player get out of a portable container before attempting to lift it – a consideration that comes up relatively rarely, but that might pertain to inflatable rafts, beanbag chairs, and other lightweight but capacious pieces of furniture.
Position Within Rooms for a box the player can push around the room and stand on in different locations.
The Human Body for letting the player sit, stand, or lie down systematically on furniture or on the floor.
Furniture for various objects on which the player can sit or stand.
We could now re-write the check rules so that any time someone (the player or someone else) tries to pick up a container which he is in, he will first get out:
With GET DOWN, we can replace the whole command, which will not interfere with the normal function of the TAKE verb, or allow the player to attempt to GET any other directions:
This doesn't cover the case where the player just types "DOWN", and we don't want to preempt the normal operation of the GO action here. So instead of writing a new understand instruction, we might catch this one at the action-processing level:
To set the scene, and make new actions to provide for two of these ways:
So far, so good. Now for the grammar, where we create two new tokens: one for each of two groups of alternative prepositions.
The standard WAIT command makes time pass at the same rate that it would anyway – one minute per turn. In a story where events happen at specific times of day, though, we might want to give the player more control. Nine AM Appointment ★ shows how to give the player a WAIT 10 MINUTES command, while Delayed Gratification ★★ lets him WAIT UNTIL a specific time of day.
Ordinarily, Inform also refuses to allow the player to SLEEP and WAKE UP: the commands exist, but have no effect. Change of Basis ★★ lets the player put himself into a sleep state in which he cannot do anything. A somewhat more interesting expansion on this idea would be to let the player sleep and have dreams; there are no examples specifically of dream states, but we might consult the examples on scenes about how to disrupt one environment and move the player to another, entirely new one.
Scene Changes for ways to move the player to a new environment such as a dream state.
If there's some reason the player needs to be at a specific place and time, we might want to allow him to wait a number of minutes at once.
The one nuance here is that after our wait command occurs, the turn sequence rules will occur one more time. So we need to subtract one minute from the parsed time to make the turn end on the desired number of minutes.
And if we want to ensure that the player doesn't (accidentally or intentionally) put the interpreter through a really long loop, we could put an upper limit on his patience:
Suppose we want to allow the player to go to sleep some of the time:
The important thing to note here is that it does not work to say "the player is either asleep or awake". This is because the player is not necessarily one specific person or thing during the game: the identity of the player can be changed, as we will see later.
So if we want to make rules about the properties of the player, we should attach these rules to the "person" kind.
Now a few rules about changing from one state to the other:
Many other actions are themselves very simply implemented and provide only a shell for us to expand on according to the needs of a particular story. Many of these are discussed at more length in sections on various kinds of props and objects; in particular:
Modifying Existing Commands for ways to override automatic takes or restrictions on what the player must be able to hold or touch.
Sounds for LISTEN.
Barter and Exchange for GIVE and SHOW.
Combat and Death for ATTACK.
Saying Simple Things for ASK, TELL, and ANSWER.
Food for TASTE and EAT.
Liquids for DRINK.
Clothing for WEAR and TAKE OFF.
Bags, Bottles, Boxes and Safes for OPEN, CLOSE, LOCK, and UNLOCK as applied to containers.
Doors, Staircases, and Bridges for OPEN, CLOSE, LOCK, and UNLOCK as applied to doors.
Furniture for things the player can ENTER and GET OUT of.
Money for BUY.
Fire for BURN.
Glass and Other Damage-Prone Substances for CUT.
Many fantasy games incorporate the idea of magic words that can be spoken. In implementing these, we want to be a bit flexible and accept a range of input regardless of whether the player explicitly speaks the command aloud: XYZZY, SAY XYZZY, or perhaps even CAST XYZZY. The inventively named Xyzzy ★ demonstrates how we might define such a command.
If we want to go even further and to allow the player also to use quotation marks, as in SAY "XYZZY", we may want to include Punctuation Removal by Emily Short, which allows for quotation marks to be stripped out of the player's input before it is understood.
We have seen before how to define a new action from scratch, but we may want to review here, using a simple command that requires no objects.
XYZZY is a magic word from the original Adventure, and many other games respond to it with some sort of amusing message.
Sometimes we want Inform to apply a player's action to a different target than the one specified: for instance, directing all (or almost all) commands from the doorknob to the door of which it is a part. Fine Laid ★ demonstrates how to do this. Along the same lines, Lucy ★ shows how to direct a player's conversation action to apply to a new conversation topic.
We can also record a series of actions performed by the player or by another character.
Cactus Will Outlive Us All ★ demonstrates characters each of whom reacts to a very specific provocation; I Didn't Come All The Way From Great Portland Street ★ implements a game show in which the player is not allowed ever to repeat an action he has already performed; and Leopard-skin ★ implements a maze which the player can escape only by performing a specific sequence of actions.
Anteaters ★★ provides a peculiar gizmo that can remember actions performed in its presence and force the player to reiterate them.
Sometimes it is useful to direct all -- or almost all -- actions from one object to another. For the sake of argument, say we have a sheet of paper with writing on it, and (because we're very meticulous) we want to let the player examine the writing and get a customized response, different from when he just examines the sheet of paper. But for all other purposes -- say, TAKE or TASTE -- we want the two objects to be treated as one.
Here, we approach the problem by changing the noun and/or the second noun of the current action, then issuing a new command to "try the current action". Because we've changed the noun and second noun, the "current action" at this point is different from the one generated originally by the player's command.
Occasionally we will want to replace the player's question topic with another of our own devising. We can do this in the simplest possible case like so:
Note that this syntax did not work in older versions of Inform; it is now safe.
220. ★ Cactus Will Outlive Us AllIf we leave it at that, then pulling the cactus will kill Luckless Luke but then say "Nothing obvious happens.", which seems like a bit of an anti-climax. So we add a special case response for that one:
Suppose (as in Infocom's Leather Goddesses of Phobos) that we have a maze that the player can escape only by performing the correct sequence of actions in the correct order. One way to do this would be to keep a list of the player's most recent actions, and see whether these match up with the combination we have established as the maze's solution.
For instance:
There is very little to this, in fact. The tricky rule to enforce is Repetition: the player is forbidden to repeat any previously tried action. We keep track of this by keeping a set of past actions, which for want of a better term is called the "tally". All we need to do is:
Note that the tally can never contain duplicates, and that when, at the end of the round, we print it out, we sort it first – this makes a more natural-looking sentence. (Sorting a list of actions uses the natural order for actions: compare the sequence on the Actions page of the Index.) The full text, then, is:
(The Paris Theatre in Lower Regent Street, London, was for many years the home of BBC radio panel games.)
| topic | reply |
| "spines" | "You flip through the Guide for a while and eventually realise that spines are flora, not fauna." |
| "anteater colonies" | "The giant anteater, which grows to six feet in size and can kill a jaguar, is a solitary animal, found in many habitats, including grasslands, deciduous forests and rainforests. It does not form colonies. That's ants. They're actually quite easy to tell apart." |
Inform allows a handful of actions – TAKE, DROP, PUT, INSERT – to apply to more than one item at a time, so that the player can move things around easily.
The general principle is that multiple objects are allowed if the actions are likely to be successful but not interesting most of the time, and if they're things that the player could plausibly do all at once. For most actions, the use of ALL would seem weirdly indiscriminate: EAT ALL, say, describes very implausible behavior, and EXAMINE ALL would likely generate a screenful of text at once.
But this is all under our control. To create an action that uses multiples, or to allow the use of multiple objects with an already-existing action, we need to create an understand statement that uses the "[things]" token (note the plural). For instance:
This would let the existing give action apply to multiple objects, in just the same way that "take" does. Shawn's Bad Day ★ demonstrates how we might allow EXAMINE ALL to print descriptions of every visible item.
Alternatively, we could generate a new action:
(In theory the language here should perhaps be "several carried things" -- but Inform is still going to process multiply-giving item by item, unless we redirect it. More about this in a moment.)
When handling an action that uses the "[things]" token, the parser makes a list of every item to which it is going to apply the action: this is called the multiple objects list. The multiple objects list can be the result of a vague request (GET ALL) or a specific one involving identical multiples (GET PENNIES, GET THREE APPLES) or a very specific one involving unique, named nouns (GET GERBIL, APPLE, AND POMEGRANATE).
We can manipulate what Inform includes in "ALL" in sentences like TAKE ALL with the "deciding whether all includes…" activity; for instance
prevents TAKE ALL from applying to things that can't be moved anyway, avoiding lots of lines like
A slightly tedious technical note: the multiple objects list is not strictly a list in the standard Inform sense, because it is used so frequently in parsing that it would be cumbersome to handle it with the more flexible but less efficient structure used for lists. However, if we want to manipulate the multiple objects list as though it were an ordinary list -- that is, sort it, rotate it, truncate it, remove entries from it, etc -- we may do so by creating a list like this:
and later after making L conform to our desires:
Inform next repeatedly runs the action rulebook for the action generated, using each item from the multiple object list as "noun" in turn (or as "second noun", if that's where the [things] token appeared in the understand line). Since it is possible to alter the multiple object list before the "generate action rule" portion of the turn sequence consults the rulebooks, we can also affect the order in which the player's matched objects are handled; see Formicidae ★★. We should not attempt to change the multiple object list after this point, because this is likely to introduce bugs.
Each time Inform tries the action on a new noun, it prefixes the action-attempt with the name of the item it's currently working on. This is where we get such output as "frog eyeballs:" and "newt toes:" in long lists like
These names are generated by the "announce items from multiple object lists rule" in the action-handling rules; Escape from the Seraglio ★★ shows how to alter them. In the context of this rule, the thing we are currently printing the name of can be called "the current item from the multiple object list".
Suppressing names of objects entirely, while occasionally tempting, may have unintended consequences, especially if some of the attempted actions are prevented by check rules that themselves print things. It is safest to suppress the multiple object names in the case where we already know that the action will succeed wherever it is attempted (more often for observational actions like examining than for manipulative actions like taking, or where we mean to completely override default handling).
Given that our hypothetical "multiply-giving" applies to each given object in turn, it might seem to be useless to create "multiply-giving" as an action different from "giving" -- but the convenience is that manipulating the multiple object list makes it possible to group behavior artificially. The trick here is that, on the first pass of the multiply-giving rulebook, we look at the entire multiple object list, perform actions, print output, and set a flag saying that the action has been handled. The flag tells Inform not to do or print anything for any of the subsequent passes through that action rulebook; thus we artificially create a situation where, instead of performing an action on each object in turn, Inform acts once on the entire group. That allows us to assess the cumulative qualities of the group and have the action respond differently than it might when assessing each item individually.
The Facts Were These ★★ demonstrates how we might write an action for GIVE THREE DOLLARS TO MAN or GIVE PIE AND HAT TO MAN where the man would only accept the collective gift when its total proved satisfactory.
Western Art History 305 ★★ demonstrates how we might allow EXAMINE, which doesn't normally permit multiple objects, to take them, but to give vaguer responses to a mass examination than an individual one.
Examining for groups of objects that have a collective description different from their individual descriptions, and for commands that search multiple things at once.
Dispensers and Supplies of Small Objects for ways to let the player pick up a number of identical items from a dispenser or supply.
We can add the handling of multiple objects to an existing action simply by adding in a line of grammar using "[things]". In response, Inform will consider every object accepted by the token, and perform the action once for each of those objects. Thus:
If a single command asks to do many things, some dull and some exciting, we may want to save the good ones for the end.
In a gallery, there are many individual things to look at, but you can also get a general impression by just examining them as a collection.
First, we'll make a kind for the paintings exhibited in the gallery, and then we'll also make a special object to represent all of them as a mass:
We could if we wanted tweak the description to be different in style in different rooms of the gallery, but this will do for now. Next we need to make it possible to type something like EXAMINE PAINTINGS, which normally wouldn't work because the Standard Rules don't tell Inform to recognise multiple objects with the EXAMINE command (unlike, say, DROP or TAKE). This is easy:
Now to make use of the special object. If the player types EXAMINE PAINTINGS, the multiple object list will become a list of the visible paintings. The following rule looks at this list: if it contains more than one painting, it replaces them with the painting-collective instead. Now there's only one examining action, so we get a reply like "There's an abstract painting, a pointilist painting and a French academic painting." instead of a list of descriptions of each in turn.
And now some art to try this out on:
Suppose we have an item that produces an interesting result the first time the player lifts it -- a rock with dangerous ants revealed underneath. The effect of the surprise is a little weakened, though, if the player sees that response as the result of a TAKE ALL, when it might be printed like this:
The calm response to "rusty nail" looks odd now, and the score change is disconnected from the event that caused it.
To manage this, we might institute a system so that interesting objects are handled last in their list, like so:
Note that while one could also manipulate the object list to add or remove items at this stage, there's a simpler way to control what Inform considers "ALL" to mean in commands: see the activity "Deciding whether all includes" in the activities chapter.
430. ★★ The Facts Were TheseOccasionally it happens that we want to process an action on multiple items differently than we would if the player had just typed each of the individual actions separately. In this example, the reason is that we can only successfully GIVE items when their combined value passes a certain threshold amount; otherwise the recipient will reject them.
This works as an implementation of money, if we give value only to cash objects (though several other implementations of cash are available, most of which are simpler and more efficient). We could also imagine a mechanic like this being used for a bargaining or auction game as well, given a society that deals in objects rather than credits.
In order to consider all the items in the gift at once, we create an action that applies to multiple objects, but will in fact test the whole object collection during the first pass and print a definitive answer to whether the action succeeded. All subsequent times the game consults the rulebook will be stopped at the very beginning. No further processing will occur or output be printed.
We start by creating the idea that everything in the game has a monetary value:
A subtlety here: we say "things preferably held" to prefer items that the player is holding (so if the player has two dollars in hand and a third lies on the ground, he will use just the two he has).
The second grammar line allows Inform to match things that aren't held if it can't make up the list from things that are. If all three dollars are on the ground, the player can pick them up before spending them.
We do not, however, make multiply-giving apply to a "carried" item, because that will generate implicit takes of those items in a way that will mess up our action reporting. Instead, we're going to build the implicit takes into the system in a different way, one that permits us to collate the reports more attractively and print a short, one-sentence list of anything that the player had to pick up.
This is for record-keeping purposes so that we can print an attractive list of what was given at the end of the turn.
"Already gave at the office" is the perhaps-excessively-named flag that keeps track of whether we've already done this action once.
The following rule is longish because it processes the entire list at once, generating implicit takes if necessary (but processing those implicit takes silently according to its own special rule, so that the output can be managed attractively). We are also, at the same time, calculating the total value of the player's offer.
The bit about making some items "marked for listing", above, rather than printing the list directly, is that using the "[the list of….]" syntax guarantees that Inform will respect grouping rules in writing its description. For instance, if the player has automatically taken all three dollars, the output will say "the three dollars" instead of "the dollar, the dollar, and the dollar."
Now we create our own variation of implicitly taking in order to customize the output for the multiply-giving action. The "ungivability rules" should disallow any object that the player absolutely cannot take, because we want "carry out the implicitly taking activity" to succeed every time -- and therefore not print out any less-attractive results from implicit takes that don't succeed. Otherwise, the player's GIVE TREE AND DOG TO ATTENDANT might produce the reply "That's fixed in place" -- without specifying which object is fixed in place.
Because of the way this works, we will want to be careful: if we have any "instead of taking…" rules for special objects in the game, we should be sure to mirror those with an ungivability rule to print something more suitable in the case that the player tries taking that object as part of the multiple giving action.
And since we don't want to list the individual objects separately:
And now, since this ought to work symmetrically if the player provides just one high-value item:
As we've seen elsewhere, the giving action by default returns a refusal, but is also written to start working if we remove the blockage. So we do that here, and revise the report rule to match the report rule we have for multiple giving.
After each instance of the multiply-giving action, we need to clear the variables we used to track its state. We could do this in "Before reading a command", but that's unsafe because the player might type GIVE PIE AND CAP TO ATTENDANT. GIVE DOLLARS TO ATTENDANT. all on a single line, and we would like to be able to clear the variables between one action and the next. The correct place to attach this behavior is immediately before the generate action rule, thus:
PURLOIN, used in the tests here, is a special debugging command that allows the player to acquire objects that wouldn't otherwise be possible to take. It is only active in non-release versions of the story. For more about debugging commands, see the chapter on Testing and Debugging.
Often we will want to replace the text produced by Inform by default: this includes quite a wide range of text, much of which either describes the success of a command or explains why the action failed.
Inform provides the Responses system to enable default messages like "You can't go that way" to be changed, and this is capable of making large-scale changes. This is especially useful if we want to give the viewpoint character a distinctive voice and set of mannerisms.
Some commands and some objects raise special challenges when it comes to working out the player's intention.
Sometimes this can be done with good rules about the assumptions Inform should make. Alpaca Farm ★ demonstrates a USE command, always a challenge because USE can mean very different actions with different items.
There are also times when we need to ask the player for more information. Apples ★ demonstrates how sensibly to use properties to disambiguate between similar objects, while Walls and Noses ★★★ rephrases the disambiguation question when special objects are involved: examining one of the walls of the room will make the story ask "In which direction?" and EXAMINE NOSE will lead to "Whose nose do you mean, Frederica's, Betty's, Wilma's or your own?"
At other times, the player types something that is wrong in a predictable way: for instance, we might want to remove all the "with…" phrases from commands like
and merely parse the remainder of the command. (That last command may be unlikely, but novice players do quite often type commands that refer unnecessarily to body parts.) Cave-troll ★★★ demonstrates how.
WXPQ ★ demonstrates how to modify the error message the parser gives in response to a command it doesn't understand; this particular example focuses on the "That noun doesn't make sense in this context" message that arises from using the "[any thing]" or "[any room]" tokens, but the techniques could be adapted to handling other parser errors as well.
For catching typing errors, Cedric Knight's extension Mistype may also be of use: it provides an automatic typo-correction function that the player can turn on or off.
This example takes the ordering of grammar lines to its logical extreme, sorting the player's input into different categories depending on the kind and condition of the objects mentioned.
Whether we actually want a USE action is a subject of some theoretical debate in the IF community. On the one hand, it helps avoid guess-the-verb problems where the player cannot figure out what term to use in order to express a fairly simple idea. On the other, it encourages the player to think that all items have one and exactly one use, rather than getting him to consider the range of possibilities that arise from having a complex vocabulary.
368. ★ ApplesInform by default detects whether two objects can be disambiguated by any vocabulary available to the player. If so, it asks a question; if not, it picks one of the identical objects at random.
Generally this produces good behavior. Occasionally, though, two objects have some distinguishing characteristic that doesn't appear in the object name. For instance, suppose we've created a class of apples that can be told apart depending on whether they've been bitten or not:
The player can meaningfully type
or
but if he types
Inform will, annoyingly, ask
This gives the player no indication of why Inform is making a distinction. So here we add a special "printing the name" rule to get around that situation:
Inform will also separate the bitten from the pristine apples in inventory listings and room descriptions, even though it's not clear why; we can improve on that behavior thus:
The parser error "That noun did not make sense in this context" arises instead of "You can't see any such thing" when the player uses a command that could apply to any item in the game -- that is, a command such as
…and so on. The idea here is that "You can't see any such thing" isn't a sensible rejoinder when the player doesn't really need to be able to see the object.
Nonetheless, "That noun did not make sense…" is itself a fairly dry and uninformative response, and we may want to override it to something more appropriate for the specific kind of context in which it might appear. For instance:
Note that this solution works as simply as it does because we only have one command in the game that can apply to an "[any]" token. If we had several, we'd need to distinguish between the parser error attached to "discuss" and the parser error attached to "go to" (for instance). In that case, we might instead write something like
Suppose we want our game to respond to "EXAMINE WALL" with "In which direction?", and to "EXAMINE NOSE" with "Whose nose do you mean, Frederica's, Betty's, Wilma's or your own?"
For the case of EXAMINE WALL, we need a way to determine whether every item being disambiguated is a direction. We'll start by making a "matched" adjective which will identify items being disambiguated:
Checking the parse list requires a bit of behind-the-scenes work with Inform 6. Fortunately, you don't have to understand this entirely in order to use the rest of the example:
Now that we've defined our "matched" adjective, we can use it for other purposes as well -- even generating our own lists. Our second challenge was to respond to EXAMINE NOSE with "Whose nose do you mean, Frederica's, Betty's, Wilma's or your own?"
Here we need to change the way the question is worded (not "which do you mean" but "whose nose do you mean"). We also have to the names of the noses as they're printed in this particular context, so that they don't repeat the word "nose" over and over. And -- as a point of good English style -- we also want "your own" nose always to be last on the list.
For this purpose we may want to use the built-in "Complex Listing" extension, which allows us to print specially ordered lists. So:
Novice players of interactive fiction, unfamiliar with its conventions, will often try to add extra phrases to a command that the game cannot properly parse: HIT DOOR WITH FIST, for instance, instead of HIT DOOR.
While we can deal with some of these instances by expanding our range of actions, at some point it becomes impossible to account for all the possible prepositional phrases that the player might want to tack on. So what do we do if we want to handle those appended bits of text sensibly?
We could go through and remove any piece of text containing "with …" from the end of a player's command; the problem with that is that it overzealously lops off the ends of valid commands like UNLOCK DOOR WITH KEY, as well. So clearly we don't want to do this as part of the "After reading a command…" stage.
A better time to cut off the offending text is right before issuing a parser error. At that point, Inform has already determined that it definitely cannot parse the instruction as given, so we know that there's something wrong with it.
The next problem, though, is that after we've edited the player's text we want to feed the corrected version back to Inform and try once more to interpret it.
This is where we have a valid reason to write a new "rule for reading a command". We will tell Inform that when we have just corrected the player's input to something new, it should not ask for a new command (by printing a prompt and waiting for another line of input); it should instead paste our stored corrected command back into "the player's command" and proceed as though that new text had just been typed.
Thanks to John Clemens for the specifics of the implementation.
A caveat about using this method in a larger game: "parser error flag" will not automatically control the behavior of any rules we might have written for Before reading a command… or After reading a command…, so they may now fire at inappropriate times. It is a good idea to check for parser error flag in those rules as well.
Very occasionally, for out-of-the-ordinary games, we want to make major changes to the way that Inform ordinarily understands commands.
Cloves ★★ shows how we might read adverbs in the player's command: adverbs are challenging because they can legitimately appear anywhere in a command structure, so must be found and accounted for before the rest of the command is understood.
Fragment of a Greek Tragedy ★★ goes further, substituting a keyword-recognition parser for the usual structure of commands and objects.
Less drastically, menus of numbered options can temporarily replace or augment standard commands. Down in Oodville ★★ demonstrates how to add a list of transporter destinations from which the player may choose by numeral.
Traits Determined By the Player for ways to ask the player a question at the beginning of play.
Saying Simple Things for a way to ask the player a yes-no question any time during play.
Now and then in IF there is a situation where we need to ask the player for a numbered choice rather than an ordinary action command. What's more, that numbered choice might change during the game, so we don't want to just hard-wire the meanings of "1", "2", and "3" whenever the player types them.
A better trick is to keep a list or table (we'll use a table here because it involves slightly less overhead) recording what the player's numerical choices currently mean. Then every time the player selects a number, the table is consulted, and if the number corresponds to something, the player's choice is acted on.
In our example, we'll have a transporter pad that can take the player to any room in the game that he's already visited. (Just for the sake of example, we'll start him off with a few pre-visited rooms.)
| transport |
| an object |
If we wanted to replace the regular command structure entirely with numbered menus, or use menus to hold conversation options, we could: several Inform extensions provide these functions.
373. ★★ ClovesIt has sometimes been suggested that IF should allow for the player to use adverbs, so that doing something "carefully" will have a different effect from doing it "quickly". There are several inherent challenges here: it's a good idea to make very sure the player knows all his adverb options, and the list of possibilities should probably not be too long.
Another trick is that adverbs complicate understanding commands, because they can occur anywhere: one might type >GO WEST CAREFULLY or >CAREFULLY GO WEST, and ideally the game should understand both. After reading a command is the best point to do this sort of thing, because we can find adverbs, interpret them, and remove them from the command stream. So:
Now we have, automatically, a value called manner understood to be used whenever parsing manners, and we can use this even during the "after reading a command" stage, so:
The qualification about turn count is to prevent this before message from occurring when the player first looks around the room (automatically) at the start of play.
Note that to test this example, one must type INSOUCIANTLY TEST ME, and not simply TEST ME: a poseur's work is never done.
374. ★★ Fragment of a Greek TragedyApologies to the shade of A. E. Housman.
| topic | reply |
| "journey/trip/travel/came/arrived" | "Sailing on horseback, or with feet for oars?" |
| "horseback/legs/feet/oars" | "Beneath a shining or a rainy Zeus?" |
| "shining/rainy/weather/zeus" | "Mud's sister, not herself, adorns thy boots." |
This would be a bit bare if we didn't provide the player with some sort of context at the outset, so let's put some remarks before the first command prompt:
This "turn count" condition is why it was useful to follow the advance time rule in "after reading a command": the game (or drama, if you like) will continue to count moves elapsed even though the rest of Inform's command parsing and world model is being ignored. In a longer and more ambitious implementation of this idea, we might want to allow scenes to govern the behavior and responses of the Chorus.
And then to give the whole exchange a play's format:
(Because this example manipulates commands outside of the normal parser, the mechanism for TEST will not work here. Try typing commands such as: TELL CHORUS ABOUT JOURNEY / TELL CHORUS ABOUT FEET / TELL CHORUS ABOUT SHROPSHIRE / TELL CHORUS ABOUT ZEUS)
Talking about characters presents some special challenges. For one thing, some characters are referred to by a proper name, but others are not: so the story might want to talk about "Jack" but also about "the drunk pedestrian". In the absence of other information, Inform attempts to divine our intentions based on the words with which we defined a new character: but we can always override its guess with an explicit statement, such as
Belfry ★ demonstrates further how titles are set at the start of play.
The relation between the player and the other characters is not always static, however. Sometimes we want the player to learn a character's name part-way through play, and start referring to "the drunk pedestrian" as "Fernando". Similarly, the status of another character may change due to some twist of the plot. Gopher-wood ★★ shows how to change the name of a character mid-story, and Peers ★★ handles changing the character's rank.
Alternatively, of course, the player character may already know some of the other characters when the story begins, even if the player does not. In that case, we may want to add a tag-line or so of identification to a character's name when he first appears in the story. A Humble Wayside Flower ★★★ shows one way of doing this.
Another occasional challenge is dealing with such commands as EXAMINE DR. THISBY. The problem here is that Inform by default will understand the full stop after "Dr" to be the end of one command and the beginning of another, and will try to interpret "Thisby" as a verb. If we do have a story populated by such formally-addressed characters, we may turn to Punctuation Removal, which provides a phrase to remove the full stops in standard titles before attempting to interpret the command.
Other characters have physical characteristics as well as names, of course, and Meet Market ★ demonstrates one way of implementing people with notable features.
Finally, in some IF, the roles of characters may change from playing to playing. If we are writing a replayable murder mystery, we might want to select a new culprit each time the story starts; for this, see Clueless ★.
The Human Body for more on body parts and physical description.
Memory and Knowledge for a way to refer to characters whom the player knows about but who aren't currently in the room.
"When play begins" is the best point to initialize any aspects of the game that are meant to change between playings. For instance, in this scenario, we would randomly select one of the other characters to be guilty of murder:
We have already seen that we can give things value properties -- a lamp has a brightness, for instance. Relations give us additional flexibility: since we may relate various things to various values, it is possible to describe a thing as having more than one value at the same time.
To demonstrate:
The same logic might be used to provide characters who have complex mood states: a person might be angry and sad, not merely one or the other -- feelings being what they are.
32. ★★ Gopher-woodSuppose that we want a character who starts out with a general epithet ("the bearded man") but is later introduced to the player properly ("Japheth"). In that case, we want to be able to tell Inform to stop using an article once the character has been given a proper name. We can do this like so:
Finally, we need to tell Inform to understand the man's name, but only when he's been introduced. For this purpose, we borrow from the chapter on Understanding:
Almost all of this example is the flummery of pomp and circumstance: only the first two paragraphs really do anything.
First we define the relationships we choose to acknowledge:
For brevity, we will ignore the existence of mothers. It is a sad world.
Monsieur St Just never appears on the scene in this piece, but if we did put him somewhere the player could find him, he, too, would be properly introduced.
A character who sits still in a chair and does nothing is much less convincingly alive than one who seems to be pursuing some sort of personal agenda. There are all sorts of ways to achieve this, but the least challenging is by introducing some random change to descriptions, and by giving a character some very simple routine behavior to carry out.
For instance, we'll often want the characters in a room to be described doing different things every time we look at them. Camp Bethel ★★ shows how this may be done.
Every turn rules lend some sprightliness to otherwise-silent characters, as well:
We might expand on this by providing a whole table of things for Mrs MacG. to cycle through, or a text variation effect that gives her different activities every turn, as in
This is no great innovation in characterization by itself, but it does at least remind the player that the character is alive and moving about, even when he isn't paying attention to her.
Annoyotron Jr ★ demonstrates a character who actively tries to get our attention, and whose routine of behavior changes just slightly if we show signs of having reacted to him.
Lean and Hungry ★★★ implements a classic thief, a character who doesn't interact with the player much except to pick up valuable objects he finds left around the map. Later we will see rather more advanced ways to make characters act on their own goals and plans, but this kind of simple behavior is easily rigged as part of an every turn rule.
Finally, Text Foosball ★★★★ extends the every-turn-rule idea to create an opponent who joins us in a randomized game of table soccer.
With animal characters, this kind of repetitive, semi-random behavior is often adequate: we don't expect animals to talk, or pursue steady goals, or to take an interest in what we do in their presence (unless it involves a food they like to eat).
For people, we are likely to need an assortment of additional techniques.
Animals for a domestic cat and dog.
One use for text alternatives is to change the description of a room after first visiting. We've already seen, in the example "Slightly Wrong", how to do this with "[if visited] … [otherwise] … [end if]". But since the first description is printed once and the second description on all subsequent occasions, we could equally well write
We might also want to liven up the behavior of people and animals, who are probably not doing the exact same thing every time we glance in their direction. There are more complex techniques for modeling the behavior of characters, as we will see in the chapters on Advanced Actions and Activities; but if we just want some textual variety, we might write something like:
And since (textual variation or not) we do want the player to be able to see all these objects:
Jeremy is following a sequence of actions to do an implied task (still somewhat robotically, but it will do for now). Animals might be a bit more capricious, though:
The housefly's description is merely "at random" rather than "purely at random" because we want to show it doing a different thing each turn, whereas Fluffy could plausibly stare out the window for five turns in a row.
There are more complex ways to change and override the initial descriptions of people and things; if text alternatives do not get us far enough, we can turn to the "rule for writing a paragraph about," documented in the Activities chapter.
Another frequent use of text alternatives is to give characters a bit of variety in things they're likely to say many times in the course of a game:
Or, with somewhat more complexity:
Notice that, in that last line, our first option is entirely blank. If we put nothing as an element of the text alternatives list, this means that printing nothing at all is a viable alternative. In fact, we've made this the most common probability out of the decreasingly likely outcomes, so that five times in fifteen, or a third of the time the text is run, there will be no modifier printed at all.
As this example (alas) reveals, text alternatives will not go all the way toward making our characters into compelling conversationalists; we will have to wait until we know more about Actions. But at least we have abolished the default responses, and given Jeremy a touch of personality, however witless.
76. ★★★ Lean and HungryNow we make the rule that governs the gentleman's behavior. Here we're going to invoke the rules that allow characters besides the player to do actions. More about this can be found in the Advanced Actions chapter:
That "not carried by a person" prevents the gentleman from stealing from the player (or, less plausibly, from himself). If we did want him to pick pockets, we could just have said "which is not carried by the gentleman".
Suppose we want a game of foosball in which our opponent acts every turn, but does different things depending on where the ball currently lies. We can put together a sequence of every-turn rules to account for this, as follows:
As we observe characters, so they observe us. Those who seem to have no awareness of what the player is doing often come across more like waxworks than like people. Zodiac ★ demonstrates a scenario where the watchful presence of a dangerous criminal keeps the player from doing what he otherwise might, while Police State ★ expands on this idea with a policeman who reacts to entire types of behavior in his presence, regardless of whether the culprit is the player or a third party. Noisemaking ★★★ has a crow who will fly away in response to any loud noises the player makes.
And, of course, we definitely want to have characters react to being looked at or otherwise interfered with. Search and Seizure ★★★ implements a smuggler who reacts when we try to confiscate his possessions. Pine ★ gives us a sleeping princess who can be woken by a variety of methods.
We wrap up this section with two complete puzzle scenarios that demonstrate what can be achieved by giving characters reactions to the player's behavior. A Day For Fresh Sushi ★★★★ has a fish who watches the player's actions and comments on them, while the live furnishings in Revenge of the Fussy Table ★★★★ instead comment every turn on the current state of the world, until the player has successfully sorted out all their complaints.
Notice that the following two scenarios do not have the same effect:
…will prevent the player from doing anything else to the killer, but allow him free range of action with other objects. By contrast, the following will prevent him doing anything other than examining to any item:
But notice that because we specified "with something", actions that take no object (like sing) are still not affected.
The most strict statement would be
Because we left "something" out, now the pattern does not have to match an activity with an object; it will match any activity at all. Singing too will be deemed too risky in the presence of our sinister foe. But we do need to make an exception for "look", or else we won't get even the room description.
154. ★ Pine 1Because scene rules are checked every turn, they can be useful for designing puzzles which have multiple solutions. Instead of deciding the puzzle is "solved" when the player does a certain action, we set up a scene that checks to see whether the player has achieved a certain outcome -- however he accomplished it.
For instance, in this scenario, we're waiting for Sleeping Beauty to wake up, and it doesn't much matter how…
Note that the policeman will never get to the second persuasion rule, so he will always refuse to do the player's nefarious bidding.
And here's an unnecessary aesthetic touch from a later chapter, which will round up the descriptions of your friends into a single paragraph:
Notice the difference between the two rules about disorderly conduct: the one for other people says 'the rule succeeds' to make sure that the action is counted as a success and not (as normally happens with instead rules) a failure. Most of the time we don't care whether actions are judged successes or failures, but it matters here, because if we type CHARLES, JUMP and the result fails, then text such as 'Charles is unable to.' will be printed – which would get in the way. So we declare the action a success.
38. ★★★ Search and SeizureSuppose we want a character who carries hidden objects, but only while he is wearing his jacket. If we deprive him of this, his other possessions become known. Furthermore, if we ever search him, his possessions also become known, and can thereafter be mentioned by us.
Now, we want the character to be able to hide small things if he has some sort of concealing garment on. We also want to be able to see anything that the player has already found once, perhaps by using the >SEARCH PERSON command. So:
The following rule, borrowed from a later chapter, assures that any items that are ever mentioned to the player will be treated as known from then on:
Notice that we can talk about what the smuggler wears, what he carries, and what he "has": things the smuggler has can be either worn or carried, so the phrase is useful if we don't care to make that distinction.
Suppose the current sequence of action handling is not quite enough for us: we'd also like to have a stage after reporting, where other characters can react to the player character's behavior after it has already happened and been reported on screen. Having such a stage is unlike using "after", because after occurs before reports and prevents them from being printed. So, for instance, we could allow the player to do any of a range of different actions that make loud noises, and have a nervous bird that reacts to all of them by flying away afterward.
To do this, we can add a new rule into the specific action-processing rules. (For a list of these, see the Rules index.) Moving rules around and adding new ones requires syntax that we will learn in the chapter on Rulebooks, but the present example is fairly straightforward:
This example does include a number of features that we haven't met yet, particularly rulebooks. Nonetheless, the basic idea should be relatively clear. Our premise is that the player is faced with a series of disgruntled furnishings, none of which want to be responsible for supporting the cold, hot, drippy, or spiky objects lying around the room.
Moreover, every time the player gets close to resolving this issue, his unhelpful companion Alison brings in something else inconvenient. We can use the counting of contented supporters to decide when the player is getting close to winning and it's time for her to bring something else…
And just so that the player knows where he stands at the end of each turn:
Finally, we need some rules to decide when the player is, in fact, finished.
The following is an almost-completely-faithful rewrite of Emily Short's "A Day for Fresh Sushi", which was originally written using the (very different) Inform 6 programming language. The -- let us be honest and call it a gimmick -- of this game is the evil fish, who has some unpleasant remark to offer on pretty much every action. But the effect would wear off fast if he repeated himself, so these comments need to be single-use only.
Inform 7's repeated action syntax makes it much tidier to write the same scenario, so:
| comment |
| "'Yeah, yeah,' says the fish. 'You having some trouble with the message, there? Confused? Something I could clear up for you?'" |
| "'Oookay, genius kid has some troubles in the reading comprehension department.' The fish taps his head meaningfully against the side of the tank. 'I'm so hungry I could eat my way out, you get my meaning?'" |
| "'I'll translate for you,' screams the fish in toothy fury. 'It says GIVE FOOD TO FISH!! How much more HELP do you NEED???" |
| comment | used |
| "'Hey, nice SKIN TONE,' shouts the evil fish. His words reach you in a spitting gurgle of aquarium water. 'You gone over to a pure eggplant diet these days?'" | 0 |
| "The evil fish is floating belly up! ...oh, curse. He was toying with you. As soon as he sees you looking, he goes back to swimming around." | 0 |
| "The evil fish darts to the bottom of the tank and moves the gravel around with his nose." | 0 |
| "The evil fish is swimming around the tank in lazy circles." | 0 |
| "The evil fish begins to butt his pointy nose against the glass walls of the tank." | 0 |
By default, Inform characters are a bit grudging about giving and sharing objects: they react with disinterest when they're shown things and refuse everything they're offered.
If we'd like to change this, we can simply remove the default "block giving" rule, as in
If we do this, giving items to characters will have the result of moving our possessions to the other person's inventory. Of course, without more customization, the player may not ever be able to persuade the other character to return his possessions. Bribery ★★ demonstrates a scenario in which a character will accept gifts if they are interesting to him, and respond with a changed attitude to the player.
Barter Barter ★★★ expands further on this by allowing other characters to trade things with one another.
Modifying Existing Commands for ways to allow the player to give or show things that he isn't currently holding.
Actions on Multiple Objects for an implementation of giving that allows the player to offer multiple objects at once, where their combined value determines whether they are accepted.
Money for ways to keep track of cash flow, physical money objects, and price negotiations.
If we want to rewrite the functionality of a command that usually ends with a "block…" rule, we will have to begin by turning the blocking off.
As it happens, correct behavior is built into the GIVE command once "block giving" is turned off, so we do not have to write a replacement report or carry-out rule; the object will be transferred to the possession of the caterpillar. But we do want to adjust the action just a little so that our gift cheers up the recipient:
Now whenever we give something to an animal, the animal will be pleased about the present. Of course, we might also want to add a check rule to giving, to see whether the offering is something the recipient really wants:
There is already a perfectly workable report rule that will describe what happens when we give something to someone, but let's say we want to report on the recipient's changed mood, too:
And the rest is all scenario:
By default, if we make no modifications, telling one player to give something to another will fail, even if persuasion succeeds. This is because the default behavior of the GIVE command is interrupted by the "block giving rule" -- since in many cases we do not want people to exchange objects freely.
However, suppose that we do want characters to be able to exchange articles freely: we allow persuasion to succeed and turn off the "block giving rule".
And now we might want to implement a way to keep track of whether the recipient character wants what's being offered:
Since we've defined this as a relation, we could change what the characters like and dislike during the course of the game, freely; for instance, characters might grow hungry and suddenly like all the edible articles.
Not all characters are friendly, and there are times when we may want to include a fight sequence. There are a number of ways to approach this, depending on whether we want to offer the player a random outcome, a predetermined one, or a combat sequence that depends partly on strategy or on having the proper equipment.
Lanista ★ demonstrates randomized combat in the style of a role-playing game. The player has a partially random chance of doing any given amount of damage; both the player and his opponent have hit points, and whichever one runs out first dies. Lanista 2 ★★ continues this idea, but includes weapons that affect the amount of of damage done. Red Cross ★ by itself implements a command that we might use to find out how strong characters are at the moment.
A word of warning about designing such sequences: a player who gets a roll he doesn't like always has the option of UNDOing a turn and re-rolling. This means that he can always win a random battle sooner or later; bad luck only means that it takes him longer (so he gets more bored and irritated as he plays through). It is possible to turn off UNDO implementation with
…but there is a good chance that this will irritate players in itself. Role-playing-style combat scenarios need careful design, lest they actively make a story less fun.
In a slightly more realistic setting, combat leaves physical remains behind, unless we're wielding some kind of futuristic weapon that evaporates our opponents entirely: Puff of Orange Smoke ★★ demonstrates characters who leave corpses behind when they die, while Technological Terror ★★★ more tamely explodes robots into numerous component parts.
Finally, we can imagine some scenarios in which, instead of allowing characters to strike at each other for random damage, we want to introduce an element of strategy. Don Pedro's Revenge ★★★ shows the rudiments of a system in which the characters can make different kinds of attack depending on where they are in a room filled with perches, barrels, and other swashbuckler props.
Saving and Undoing for more discussion of handling random behavior in games.
We start by recording, for each person, a maximum number of points of damage the person can sustain when starting from health, and the current number of points remaining. In the tradition of role-playing games, these are referred to as hit points.
Now our rule for the actual attack. We want first to calculate how much damage the player's attack does, inflict that damage, and remove the enemy if he's dead; then, if he doesn't die, the enemy counter-attacks, also for a randomized amount of damage, and if this kills the player, the game ends in defeat.
This last bit is a refinement to help the player keep track of how the contest is going:
Suppose we want to let the player kill characters, leaving behind corpses.
Using our "part of every person…" line, we've conveniently assigned one body per person. Since we're going to separate people from their bodies when the bodies die, though, we also want a more permanent relation that will help us keep track of which bodies used to belong to which people:
When Lydia is alive, we want >TOUCH LYDIA'S BODY to mean the same thing as >TOUCH LYDIA, so we use the setting action variables rules as a convenient point at which to reassign the action:
This doesn't change Inform's idea about what action is being performed; just about the object it's being performed on. The rest of the action will now proceed as if the player had typed >TOUCH LYDIA.
Along similar lines, once Lydia is dead, we want >MOVE LYDIA to mean >MOVE LYDIA'S BODY if the body is in view:
The trick is, though, that >MOVE LYDIA will only be understood if there is something called Lydia that the player can see and refer to, even after she's dead. There are various ways to do this, but the least painful here will be to make the deceased Lydia permanently visible, by putting her in an always-accessible backdrop. The backdrop itself will never be mentioned in the game, and we should make its name something that the player is unlikely to type casually; we don't want the player to interact with it directly. So:
It's also possible that the player will type something like >X LYDIA when Lydia's corpse is not in view, so we should have an appropriate answer to that as well:
Because the before rules happen after the setting action variables rules, this will only ever happen if the corpse is not visible.
Now we define the attack itself, which should discard the body, move the spirit to its eternal resting place, and describe the event to the player:
And finally a trick borrowed from the chapter on understanding, so that we can refer to "Lydia's body" while Lydia is alive, but "Lydia's corpse" only after Lydia has died:
Back in the chapter on randomization, we explored a way to create a randomized combat system. That system didn't allow for multiple weapons, though. Here we explore how to create an ATTACK IT WITH action that will let the player choose between weapons with different maximum powers.
We're also going to rewrite that original "instead of attacking:" rule into an attacking it with action that can be performed equally by the player or by any of the player's enemies.
In our simpler version of this example we set the current hit points by hand, but in a game with many characters this would get dull and repetitive, so here we'll use a "when play begins" to set all current hit point values automatically to maximum:
In our new system, we want to specify what is being used for an attack. This means that we need to create a new "attacking it with" action, and also that we should disable the existing "attacking…" command.
Here's why: If we leave the default attack command in place, Inform will continue to accept commands like >ATTACK GLADIATOR, but reply foolishly with the default "Violence is not the answer…" response.
A somewhat better approach would be to change the reply of >ATTACK GLADIATOR to say something like "You must specify a weapon to attack with." But this is still less than ideal, because it means that the player has to then rewrite his entire command. If, on the other hand, we take out "ATTACK GLADIATOR" entirely, the game will always prompt "What do you want to attack the gladiator with?" -- which teaches the player the correct command structure for this particular game, and avoids pretending to understand any command that is not meaningful within this game.
This is a little bit of work because ATTACK has a lot of synonyms in the default library, but if we look through the actions index we can find them all:
Now we make our new command:
Note that we've specified "one carried thing", because we want the player to pick up a weapon to use if necessary. And now we assign all the old attack vocabulary to apply to the new command:
This may seem counter-intuitive, but order of source code matters here: we first get rid of the old, default vocabulary, then define our new action, then make the vocabulary apply to that new action. Inform will now understand >HIT GLADIATOR WITH TRIDENT, >BREAK GLADIATOR WITH TRIDENT, and so on.
Our new action is also a perfect place to use an action variable: we're going to need to choose an amount of damage done and refer to that several times in our action rules. So let's set that up first:
Though our checks and carry-out rules are similar regardless of who is acting, we're going to want actions to be described differently for different actors, so we'll use separate "report attacking" and "report someone attacking" rules. We'll also make some special cases for when the character has died as a result of the attack:
Those devoted to role-playing will note that our form of randomization is still pretty naive: most RPG systems use multiple dice in order to create more interesting probability curves. For a system that simulates actual dice-rolling, see the full "Reliques of Tolti-Aph" game.
113. ★★★ Don Pedro's RevengeSuppose our game features a detailed simulated combat between the player character and his opponent. He might have several weapons available, and several types of attack available; and at any given time he might be perched up in the rigging of his ship, standing on the open deck, or boxed in between some barrels. His options will vary depending on his position, and obviously it would detract from the pacing to make the player keep LOOKing in the middle of combat in order to remind himself where he is. Instead, we'll roll this information into the command prompt:
| position | prompt |
| boxed | "So securely boxed-in that you can really only parry or thrust, you try to " |
| boxed | "Trapped between your barrels, you decide to " |
| perched | "Able to slice at your attackers but not to advance or retreat, you choose to " |
| perched | "Perched up here with the advantage of height (but little mobility), you attempt to " |
| free | "Out on the open deck with no impediments, free to advance or retreat, you decide to " |
Of course, this won't be much fun until we also provide the player with a few weapons, some more fighting maneuvers, and, most of all, a Don Pedro to defeat.
127. ★★★ Technological TerrorFirst we need to define our shooting action:
Next, some grammar to allow the player to use this action:
Strictly speaking, we only need these last grammar lines (with "understand shoot something…") in order to define an action that the player can take. Adding more grammar lines means that Inform will try to match the most specific ones first, which is useful when the player types something ambiguous and there is one choice that obviously fits this action better than the others. See the chapter on Understanding for a further discussion.
Here we get to use "now…" to give it its destructive effect:
Traditionally, conversation is one of the most difficult things to program in interactive fiction, because of the number of factors affecting the outcome of everything the player does. While it's acceptable for >EXAMINE POT to produce the same response every time the player types it, it's a bit less acceptable for ASK JOE ABOUT HIS ADULTERY to make Joe react the same way every time.
Conversation implementations often need to keep track of a lot of information: what else is going on in the model world, what the character knows, what plot phase we've reached, what mood the character is in, what else we've recently been talking about, whether we've said the same thing before (and how many times); and so on. Later in this chapter we will look at ways to model character knowledge and mood.
Then, too, we have the problem of how the player communicates his conversational intentions to the story. Technology has not yet advanced to the point where a player can simply type in remarks in full natural English and have the character detect the significance, emotional tone, and subtext, if any: so we can't have RACHEL, THIS DESSERT TASTES LIKE FEET or WILL, LOOK! OUR SINISTER METAL FOES ARE APPROACHING! or BOSS, I WOULD BE DELIGHTED TO FILE ANOTHER TPB REPORT.
The challenge is to create an interface that is both easy for the player to use and expressive enough to be interesting. We will look at some of the common solutions in "Saying Complicated Things".
The examples in the following sections point out ways to approach common conversation problems. None of them will offer an adequate system if we want to write a very conversationally rich story, however. This is partly because a thorough conversation system requires quite a lot of code in its own right. It's also partly because there is no one right solution to the problem of conversation design. Different games will have quite different requirements. When making decisions about a new story we have planned, it may be useful to glance through the conversation extensions available for Inform: there are quite a few, offering a range of different interfaces. Even if none is exactly suited for our needs, they may suggest ways to solve particular implementation challenges.
At the other end of the scale, though, there are times when Inform's default implementation is too complicated for what we want to do: so we will start with ways to simplify conversation, before moving to all the exotic complexities.
Before we get into these details, though, we have a couple of examples that are literally about getting started with a conversation: Mimicry ★★★ introduces the feature that we must greet other characters before beginning to speak to them; The Gorge at George ★ corrects the player's attempts to use a TALK TO command where a different mode of interaction is appropriate instead.
Suppose we want to add a sense of some conversational flow, so that the player is forced to acknowledge the presence of people before beginning detailed conversations with them. We collect all speech actions into a single category:
And then write a general rule.
One complication is that "asking someone to try doing something", which describes commands such as FRED, GO SOUTH, cannot be made into a kind of action. This requires its own rule:
Now we define what greetings are going to look like:
Because of the way we've defined the command, this will now also work if the player waves.
And now the scenario:
There are times when even the commands ASK and TELL are overkill: sometimes the player doesn't have much information to offer, so TELL is never useful, for instance. If we don't want to make any distinction between modes of conversation, we can conflate the actions so that ASK LUCIUS ABOUT OLLIVANDER, TELL LUCIUS ABOUT OLLIVANDER and LUCIUS, OLLIVANDER all do the same thing: see Sybil ★.
If we are frequently permitting the player to say things like LUCIUS, OLLIVANDER as shorthand for "talk to Lucius about Ollivander", then we may also want to allow LUCIUS, OLLIVANDER? This makes the player character seem a bit slow (or at least Laconic), but it is an effective interface in some cases. The trick is that the question mark at the end of the command may prevent Inform from recognizing the keyword; should that problem arise, we may want to use Punctuation Removal to erase question marks from the player's command before attempting to interpret it.
Along the same lines, there are situations in conversation where similar commands do not correspond to the same actions within Inform; if we're careless about this, we may force the player to guess which vocabulary we want him to use, which is always vexing. Some cases to look out for:
Inform has actions for "saying yes" and "saying no". Sometimes this is useful, but sometimes we want YES and SAY YES TO FRED to do the same thing. Sybil 2 ★★ shows how to roll these responses into one; Proposal ★★ expands on the idea to show more ways in which a player could reasonably answer a question put by another character.
Again, if we want ASK SYBIL ABOUT CAKE to do the same thing as SHOW CAKE TO SYBIL, we might use the technique in Nameless ★★ to make objects into valid topics of conversation, and to make ASK and SHOW behave the same way.
Finally, if we want to be able to ASK and TELL an inanimate object -- say, a computer -- about something, we may use the extension Inanimate Listeners to add this capability.
Remembering, Converting and Combining Actions for ways to redirect one conversation command to another conversation topic.
Varying What Is Read for a way of asking the player trivia questions that he can answer only on the next turn.
Sometimes we do not particularly want to deal with all the variations on asking, telling, or answering someone something, but want to direct everything to a single conversational command:
And similarly, a difference between GIVE and SHOW is sometimes overkill:
It is also often the case that we want to accept more than one form of a term. For instance
will match either "Darius" or "king". If necessary, we can go a step further and define our own token to match a variety of phrases, like this:
The token "[Greeks]" will match all of "Athenians", "Spartans", "Greeks", "hoplite army", or "hoplite forces". It will not match "hoplite" or "forces" alone; it is important to note that the / divides individual words which are understood equivalently, but does not define entire phrases as equivalent. More about how Inform understands specific phrases can be found in the chapter on Understanding.
Inform already understands YES, NO, and SORRY as commands in their own right, which can make things a little sticky when we want a character to ask a question of the player. The most important thing is not to cover some of the possible phrasings while ignoring others.
The complexity arises from the fact that we want to handle both YES and SYBIL, YES. If we only had the latter, 'yes' would be treated as a text given to the Sybil, just as in the commands SAY YES TO SYBIL or ANSWER YES. But because we have defined it as a command (so that the player can use it independently), SYBIL, YES is understood as an order to the Sybil to do the YES action.
Fortunately, we can redirect everything, as here, so that the results wind up the same.
And if we want yet another variation not covered by the Inform standard:
But that is a matter for a later chapter.
Suppose we want to ask the player a question where he might say yes or no in response. There are two possible forms of this: the modal question where the player must pick one to proceed, and the non-modal question where he might also type other verbs.
And since the player might SAY YES TO SPRUCE, we had better reroute the relevant options:
By default, ASK SOMEONE ABOUT… applies only to a text token. We might want also to offer the player the option of asking characters about pieces of physical evidence. This example implements an ASK PERSON ABOUT THING command that is mostly synonymous with SHOW, with the added nuance that the player can ask about things that are not currently visible, as long as he has encountered them at some time in the past.
Now we create our new action, "interrogating it about". We write the grammar lines so that we can show any object in sight to someone, but also ask someone about any object that we have ever interacted with in the game, whether it is currently visible or not.
Now we replace and redirect the showing action. This gets rid of the requirement in the default library that the player be holding anything he shows to another character:
This bit keeps track of what the player has seen, for the purposes of "any known thing":
Here we define what happens by default when we interrogate someone about something; we use the same response we get to asking someone about something that isn't otherwise interesting:
Now redirect all asking to a topic table, and all interrogating to an object table:
| item | reply |
| letter | "'It is enciphered,' she remarks[if the advisor can see the letter], glancing over the contents[otherwise], after you have offered a detailed description[end if]. 'A substitution cipher of some complexity, I believe.'" |
| Advisor | "She listens to your inquiries about her identity and parentage with a placid smile, but does not answer." |
| topic | reply |
| "cipher" | "'I know many dozens of ciphers,' she replies, smiling in a disquieting way." |
| "substitution cipher" | "'One letter is allowed to stand for another,' she explains, folding her hands together patiently. The backs of both hands are tattooed with silvery stars." |
And just so that we can test what happens when asking someone about something out of sight:
…and something unknown:
As we saw in the overview, there are challenges in choosing the commands with which the player will communicate to the story. Two common approaches are ASK/TELL conversation, where the player can ask or tell characters about keywords, as in ASK JILL ABOUT JACK or TELL FARMER ABOUT CHICKEN COOP, and menu-based conversation, where the player is offered a list of things to say and must pick one (often by number), as in
or, sometimes,
The problem with ASK/TELL conversation is that it can feel undirected – if the player doesn't know which keywords to ask or tell about next, he gets stuck. It also doesn't always provide much sense of ongoing context or conversational flow, since the player can ask lots of unrelated questions and jump around a lot. What's more, sometimes the thing the player character asks isn't quite the question the player had in mind. If we type ASK JILL ABOUT JACK, Jill could wind up answering any of a number of questions – where Jack is, how old Jack is, whether Jack committed the recent murder, and so on. The player doesn't have much fine control over the conversation. Nonetheless, this is sometimes just what we want: Farewell ★★ implements a moderately sophisticated system along these lines, which keeps track of what the player has already said and allows him to review past conversation.
Menu-based conversation solves most of these problems: a branching tree of conversation choices maintains a consistent flow of discussion, it's hard for the player to run out of things to say, and the player always knows what his character is about to say. But there are compensating flaws. For one thing, a menu doesn't allow for many surprises. The player can see all the conversation the story has to offer by working methodically through all the menu branches. (This problem is sometimes referred to as the "lawnmower effect", since the process of seeing all the conversation is like the process of running a lawnmower over every inch of the lawn. It becomes a chore rather than an entertainment.) Menu systems can be long-winded to set up and therefore none are exemplified here, but several have been released as extensions for Inform.
Since about 2001, more and more IF has used a sort of compromise method: the player is allowed to ask or tell about keywords, but he's sometimes given prompts about things to say that follow naturally on the conversation he was just having, as in
Moreover, when he asks about a topic where many comments are possible, he'll be allowed to clarify, either using a menu or through a disambiguation question such as
Sweeney ★★ implements one such hybrid type of conversation.
A third option is to take away almost all the player's expressiveness and give him just one command, TALK TO. The player can TALK TO characters whenever he wants, and the story will pick the most appropriate thing for him to talk about. This works best in works with few or simple puzzles and a fast-moving, constrained plot, where the player will keep having new things to talk about. Cheese-makers ★★★ demonstrates this.
Finally, a few extreme games try to fake natural language understanding by looking for keywords in the player's input, rather than an exact grammar. This is perilous, because it is all too easy for the story to completely misunderstand what the player meant to type. Nonetheless, for the sake of example, see Complimentary Peanuts ★★★, in which the incomprehension is partly excused by the fact that the player is talking to someone a bit hard of hearing.
We begin with the idea that each person comes with his own table of things to say:
For the sake of simplicity, we'll conflate asking and telling here, though it would certainly be possible to have a more complex implementation if we want the characters to be told things as well.
Now we might want to add a recap command to review conversation that has already occurred.
Since we've been recording the turn count of each conversation bit, we can even present these in order by sorting the tables first.
Now it remains only to create a couple of characters and provide them both with something to say:
| topic | reply | summary | turn stamp |
| "aasvogel" | "'Oh, it's a vulture.'" | "that an aasvogel is a vulture" | a number |
| "acaudate" | "She shrugs, mid-pour. 'Means something doesn't have a tail.'" | "that acaudate means 'tailless'" | -- |
| "absorptiometer" | "'It's a thing that measures the solubility of gases in a liquid,' she explains gently, as to a child." | "that an absorptiometer measures solubility of gasses in a liquid" | -- |
| topic | reply | summary | turn stamp |
| "baccaceous" | "'Something that has or bears berries,' says George, without looking up." | "that baccaceous means berry-bearing or berry-like" | a number |
| "bagheera" | "'Oh, that'd be a velvet-like textile.'" | "that bagheera is a velvet-like textile" | -- |
| "balistarius" | "'That's a crossbow-man,' George replies instantly." | "that a balistarius is a crossbow-man" | -- |
A word of warning: this system does assume that every person in the game has a conversation table defined. If that were not the case, we would have to be a bit more careful.
As always, we can override specific words, too:
| subject | conversation |
| pies | Table of Pie Queries |
| employment | Table of Job Queries |
| quip | discussion | label | subtopics |
| "whether there is a job available here" | "'Say, are you hiring?' you ask, as casually as you can manage. [The interlocutor] looks you over dubiously. 'I might be hiring someone, but I can't say it would necessarily be you.'" | 0 | -- |
| "what happened to that boy that worked here" | "'Tell me, didn't you used to have a young assistant working here?' She shrugs. 'Young men these days are so unstable. He left-- who knows where he's gone? I haven't seen hair or fingernail of him for weeks.'" | 0 | -- |
| quip | discussion | label | subtopics |
| "what pie fillings are available" | "'What pies do you have in today, Mrs Lovett?' you ask. She starts, then smiles. 'Meat pies, of course.'" | 0 | Table of Pie Flavor Queries |
| quip | discussion | label | subtopics |
| "what kind of meat" | "'What kind of meat goes into these pies, Mrs Lovett?' you ask pressingly. She looks shifty. 'Whatever the butcher brings this week,' she says. 'With the price of meat what it is, when you get it, you have to be glad of what you can get. If you get it.'" | 0 | -- |
As we have seen, there are a number of different ways of controlling conversation in interactive fiction, and the best choice of way will depend quite a lot on what kind of work we're writing.
One common model is to replace Inform's default ASK and TELL commands with a TALK TO command. This gives the player less control than he would otherwise have: instead of asking a character about any topic under the sun, he's restricted to seeing (or not seeing) a single sequence of text that the author has written in advance. On the other hand, such a system is harder for the player to break (since he can never ask about a topic that the author hasn't implemented), and easier for the author to tie into plot developments. If we give TALK TO different output at each scene, we get conversation that is always tied to the current state of the plot.
This is a design approach that works best in a game with a large number of short, focused scenes. For other kinds of conversation system design, compare the other examples listed in the Recipe Book.
Here, using some techniques that will be discussed in the chapter on Understanding, we get rid of Inform's default handling of ASK and TELL, and create our own TALK TO action instead:
Now, suppose we have a situation -- say, a stage play -- in which it is appropriate to talk to different characters at different times. During the prologue of the play, no one else is on-stage, and the player is to address the audience directly:
But there might follow a scene in which the player shouldn't talk at all:
| output |
| "The chorus now begins its entry, accompanying with anapestic song its march up the eisodos." |
| "The chorus draws nearer, stomping and clomping and swinging their baskets of cheese." |
| "You stand aside as the chorus fills the orchestra and dances to and fro." |
| "The tune of the aulos-player grows more and more frenzied and then breaks off." |
This last rule is a refinement borrowing from the Activities chapter, which gives characters different appearances in room descriptions depending on when we happen to look; because of the action of the play, we want to show the chorus and audience doing different things during different scenes.
And now a scene in which the player can talk several times to a character (Heracles) but has no useful dialogue with the chorus, the audience, or himself. The prohibition from talking to the audience after the Prologue is already written, but we'll supply some appropriate responses for talking to the player or the chorus during this scene:
| output |
| "With a fart and a roar, Heracles asks the world at large, and you in particular, where his dinner might be." |
| "In epic diction, Heracles invites the dairy-mistresses, whey-matrons, and concubines of curd to supply him a supper from their ample baskets." |
| "Heracles and the chorus banter about the proclivities of cheese-wives. The chorus suggest that Heracles, as a son of Zeus, must know something about the appetites of which they speak." |
| "Heracles boasts that a man like himself can perform any feat, but only when his belly is full. Coyly, the matrons prance and dance, skip and gambol out of his grasp, singing mockingly about heads of garlic and loaves of sesame-crusted bread." |
| "The song of the feta fanciers now turns to pots of honey and new-made wine, borrowing verses from last year's Lenaia winner, 'The Bees'. With a jolt, you realize that you've missed your cue and the chorus are filling in for you." |
| "Playing for time, the chorus-leader elaborates a whole banquet: rabbit stew, shanks of lamb, spitted quails, eels from lake Copais. Heracles looks as near swooning as any girl fresh from Brauron." |
| "The chorus-leader extends the list of delicacies to include ox-brains, ham-hocks, barley, mullet, carrots, pigeons, lentils, radishes, peas, and apples both wine-dark and golden. The audience shifts on the benches. An expression of gloom settles over the Priest of Dionysus in the front row." |
| "Inspired by Euripides['] own Muse, the chorus-leader invents a mock-Alcaean hymn on the merits of chervil. This is clearly his swan-song: if you don't speak at last, the play will come to a halt." |
| "Silence descends." |
The "reading a command" activity is not the only point at which we can interact with snippets, as it happens; it is merely the most useful. "The player's command" can be consulted at other points, however, as in this example of your somewhat deaf (or distracted, or simply cussed) Aunt:
The topic understood is also a snippet, so that whenever one has been generated, we can treat it in the same way as "the player's command":
This is superior to checking "the player's command" because we do not want ASK MARTHA ABOUT FRENCH FRIES to trigger the "Martha" keyword, only the "french fries" keywords.
| topic | commentary |
| "shuttle" | "'Shuttles! I hate shuttles,' Aunt Martha grumbles. 'Give me an airplane! AIRPLANE.'" |
| "airplane/airport" | "'Those were the days,' Aunt Martha agrees, plainly reliving the days when she wore a blue-and-white uniform and passed out packets of salted pretzels." |
| "rations" | "'Do you think there are any peanuts in there?' she asks in a wistful tone." |
This means that Martha will respond to keywords regardless of the setting in which they occur. For instance:
This is not the stuff of which Loebner-winning chatbots are made, admittedly, but it is occasionally a useful alternative to stricter modes of command-parsing.
All this discussion of conversation commands and ways to model dialogue doesn't address the higher-level design issue: how do we approach writing this material so that it has a rhythm and flow? How do we know when we've created enough conversation? How can we avoid sounding hopelessly stilted when the nature of IF implementation requires us to break our text into small snippets?
While most authors develop their own approaches, there is some general advice that may help, especially for works that have a strong narrative progression.
It helps to have the plot of the story, with all its component scenes, planned in advance. That doesn't mean there can't be any changes later, but having a list of the different scenes can help us remember the different contexts in which information can appear. If we're using Inform's scenes feature, we may even want to restrict some dialogue to be available only during a given scene.
The next step is to go through scene by scene and create the "spine" of the scene. What must be said during this section? Is there anything the player can't leave without knowing? If the player isn't moving the scene forward fast enough, will the other character or characters volunteer information in order to keep the pace going?
It often helps to draft a transcript showing what we imagine as the ideal playthrough of the scene – writing straight through can create a natural flow of dialogue – before dividing the dialogue into pieces for implementation.
Once the scene is complete enough for the player to get through from beginning to end, we can start filling it out. At this point, it sometimes helps to play through the scene a number of times and add new dialogue elements as we think of things that our character might reasonably want to say. Sometimes these additions will turn out to be short tangents from the main flow of a very directed scene; sometimes they might be important branches that lead the scene to an entirely alternate outcome. The main thing is to make sure that, if the scene needs to hit certain points before ending, none of our branches keep the player from returning to the subject at hand.
In a complex story, characters may evolve strong feelings about the player. Often we want to hint at the character's feelings through gesture and tone of voice – little things woven into dialogue and action sequences that might otherwise be unchanged. Ferragamo Again ★★ demonstrates creating phrases to give all our characters different ways to express their irritation at the player.
Then again, sometimes a discussion might produce quite spectacular results if a character is in the wrong mood. Being Peter ★ shows the bare bones of an implementation in which a character's attitude rulebook is consulted to determine what her response will be – allowing for arbitrarily complicated outcomes.
Let's say that we're implementing a particularly irrational and volatile character. Some of the time she remains composed; some of the time she reacts with unexpected vehemence for reasons only partly related to what was said.
Moreover, her responses are divided between successful and failing outcomes, where success indicates that she's not too upset and failure means that she is distraught; we use this to determine how the rest of the room reacts.
Here we want Inform to consult every appropriate attitude rule until it gets to some answer; if an attitude rule does not provide a result, the default 'no outcome' will mean that we go on to the next rule, and so on.
Now, as we saw, the 'no outcome' result will never be returned and printed as Maggie's reaction, precisely because it is "no outcome". Therefore, we provide a final attitude rule which will give her a default response to all statements:
There are plenty of contexts where we might want named outcomes for clarity but not want to print the results literally afterward.
170. ★★ Ferragamo AgainHere we use phrases that match individual items where possible, and the general kind otherwise:
A character may be endowed with knowledge and even reasoning skills. Relations form quite a good way of keeping track of such problems: for instance, we can allow characters to be acquainted with one another with a relation such as
Or we might keep track of more complicated attitudes between characters, as in Murder on the Orient Express ★★, in which some characters suspect others of the crime.
Alternatively, we might have a list of salient facts that are important in our story. We might declare these as values, and then characters could know, learn, and forget entries as appropriate:
| fact | summary |
| shoe-size | "Lucy wears a size 9 shoe." |
| sunset-time | "Sunset is at 8:22 PM this evening." |
Or again we might keep a whole database of information in a table: the characters in Questionable Revolutions ★★★ know dates, countries, and a short description for each of several rebellions and popular uprisings, while in Queen of Sheba ★★★, Solomon is able to answer who, what, where, when, and why questions about a range of topics. This kind of approach is most useful when the characters need to display a deep knowledge of a particular field. The facts stored in the Table of All Known Facts, above, are comparatively sparse, because there we are designing a story in which not all data about the world is equally valuable: Lucy doesn't know the shoe size of every person in the story, because for some reason it is only her own shoe size that matters. On the other hand, the Table of All Known Facts can store different kinds of information, whereas the revolutions table has no way of storing shoe sizes or sunset times. And Murder on the Orient Express ★★ works differently again, because it is storing knowledge that concerns people and things that already exist in the world model, rather than abstract ideas. Our way of modeling character knowledge, in other words, will depend quite a lot on what kind of knowledge it is.
The possibilities of character reasoning are similarly broad, but The Problem of Edith ★★★ introduces one kind: the character has a concept of how different conversation topics relate to one another, so that when she is asked about a new keyword, she picks a response that makes the question most relevant to the conversation already in progress.
We end with a longer scenario, in which we track what the character knows about the player and the conversational state: in Chronic Hinting Syndrome ★★★★, the main character guides conversation in the direction he intends it to go, with the player's sometimes-reluctant participation.
Obedient Characters for a character who needs to be taught how to perform actions before doing them.
Characters Following a Script for a programmable robot who can be given whole sequences of actions to perform.
The following example creates two new relations, and two new verbs, in order to set up a tangled web of intrigue.
Given this, we can then set up elaborate rules:
And so on: "if Dalgliesh suspects someone who is exculpated by something carried by the player…", for instance, makes a fitting final example for this chapter. The description
expresses a complicated idea in very few words, and in such a way that a passer-by looking at the source text would immediately see what was meant.
The moral is that relations allow sophisticated patterns of behaviour to be created in a way that reads back naturally as English.
235. ★★★ The Problem of EdithSuppose that we have a core set of issues we want to be able to bring up with all the characters, and we want characters to draw intelligent connections between different conversation topics. We will need some model of how things relate to one another, so:
And if we wanted to offer the player some hints about angles he could pursue:
For that matter, we could use the same system to have characters make sense of any physical evidence the character shows them:
Now we can define what gets said when the subject is changed, regardless of whether the segue was introduced in speech or by a shown object. Since rows are blanked after use, the speaker will never repeat herself; if we provide more than one line about the same pair of topics, the first one will be used, then the second, and so on, until the table runs out:
| starting | final | comment |
| divorce | love | "'As it seems to me, all the love is on one side,' she says crisply. 'And that rarely works.'" |
| divorce | love | "'Stop making that plea: it won't work.'" |
| divorce | infidelity | "'Frankly, I rather think there would have been cause enough for divorce without the perversely plentiful evidence of unfaithfulness.'" |
| divorce | money | "'If you mean that the divorce will be expensive, I know it,' she says. 'But I can think of no happier investment.'" |
| marriage | money | "'If you wish me to understand that it was a marriage for money, you could have spared your energy. That was patent from the outset.'" |
| infidelity | money | "'I'm sorry, but I don't see how having married for money excuses a subsequent infidelity.'" |
If we had more than one character in the scenario, we could provide multiple tables, but this will do to demonstrate the idea.
Of course, we can override specific instances, if we want the character always to say the same thing regardless of how we came to this point:
We would have to be careful about this system, since we have applied a various-to-various relation to every single object in the game. In practice it would probably be wisest to restrict it a bit, with judicious definitions of kind and so on.
278. ★★★ Questionable Revolutions| topic | date | place | definition |
| "velvet revolution" | 1989 | Czechoslovakia | "A bloodless revolution in Czechoslovakia, in which popular protests led to the resignation of the communist president Gustav Husak, and the election of Vaclav Havel in his place." |
| "rose revolution" | 2003 | Georgia | "A revolution in which President Eduard Shevardnadze was interrupted by protesters in the middle of his speech, and forced to flee." |
| "spanish revolution" | 1936 | Spain | "An anarchist and socialist movement during the Spanish civil war." |
| character | years | geography | general comprehension |
| Dr Tweedy | correct | correct | correct |
| Ms Finch | erroneous | erroneous | correct |
| Ms Clarion | vague | vague | erroneous |
We have so far seen several ways to write conversational characters in Inform, and we will see more before the end of the manual. This naturally raises the question, which should we use? To which the answer is: it depends on the sort of game we're writing, and what we want our characters to do. The more rich and complex the system, the more likely that it will require a lot of content; if we add question types as well as keywords, for instance, we instantly multiply the number of responses we have to write by five or six. It is not worth doing this unless there is some corresponding advantage within the game.
279. ★★★ The Queen of ShebaSuppose we want the player to ask questions of slightly more complexity – we might want to build in a system that understood "who", "what", "where", and "when", for instance. We could use a topic table for this, too:
| topic | question type | reply |
| "rain/weather/clouds/cloud/rains" | what | "'Clouds are a disturbance made by the paths of birds,' Solomon replies. 'The air beaten by their wings becomes agitated, as when a river is stirred and the mud churns up.'" |
| "rain/weather/clouds/cloud/rains" | where | "'Weather is contained in a great silk bag which holds in the heavens,' replies Solomon." |
| "hunger/food/eating" | when | "'Sorry, are you getting hungry?' he says, and rings a bell to summon servants." |
| "hunger/food/eating" | why | "'Men were made to need food in order that they must farm and cook and dine together,' Solomon replies. 'Otherwise, they might live apart, each sufficient in himself. But no man can feed himself alone all through his life.'" |
| "Solomon/he/himself" | who | "'As you see,' he says, holding out his arms to each side." |
| "Solomon/he/himself" | what | "'I am an ordinary man,' he answers." |
One of the nice things about this system is that it only resets the "current question" when we get a new question word. For instance, this test will produce different replies to the question about Solomon himself, because the second time he is still in the mode of answering "what" questions:
If Solomon is to live up to his reputation at all, his wisdom table will have to be quite a bit longer – though one also would want to be careful, because forcing the game to cycle through a really immense table could be quite time-consuming. In fact, for the sake of this example, let's reward the player for managing to stay within the (narrow) range of Solomon's knowledge:
In a real game we'd need to be a great deal subtler. All the same, if we have a character of quite limited resources to present to the player, it's a good idea to give the player some incentive to stay on topic, ask questions the character can answer, and generally interact within the parameters we're prepared for.
Now, this last bit requires some trickery from later chapters, particularly those on Understanding and Activities, to pull the question words out of the player's command:
And now we have a game that will accept (though not always respond very sensibly to) questions of almost any form we might put to another character: ASK SOLOMON WHAT RAIN IS will be answered, but then again, it won't be distinguished from, say, ASK SOLOMON WHETHER THIS PERSISTENT RAIN IS A DIVINE PUNISHMENT OR WHAT.
All the same, a system that allowed the player a bit more specification of questions than simple keyword-use might be useful in a mystery game, for instance, where we might want to let our detective conduct inquiries into specific details. An alternative approach to the rather free one above would be to force the player to use only questions of the form WHAT IS RAIN? or WHO ARE YOU?: this would cut down on false-positive matches. But we might still choose to store the responses in a table of this type.
341. ★★★★ Chronic Hinting SyndromeSuppose we have a conversation system in which it is important to keep track of which subjects the player has heard mentioned. If we're careful to mark subjects in brackets, we can use the "printing the name of" activity to record which things have been mentioned so far:
Now suppose that as an added convenience for the player, we let him turn on a mode in which useful conversation topics are always automatically highlighted in the text, so he doesn't waste his time trying to follow up dead leads:
…And the rest is peripheral.
| line |
| "'It actually is kind of a funny story about [the random pending subject],' [Nathan] remarks casually." |
| "[Nathan] chuckles under his breath. 'Man, I hadn't thought about [the random pending subject] in ages.'" |
| "He glances sideways at you. 'It's nothing personal, you know, but I don't feel comfortable discussing [the random pending subject] with just anyone.'" |
| "'I don't know why I brought up [the random pending subject] just now,' [Nathan] comments. 'Don't mention it to anyone, if you don't mind.'" |
| "'Okay, see, the thing about [the random pending subject] is...' [paragraph break]'Yes?' you ask, on cue.[paragraph break]'...never mind.'" |
| "[Nathan] makes an explosive exasperated sound. 'Don't you want to ask me about [the random pending subject]?' he demands." |
So far we've seen characters who will answer questions whenever the player feels like asking, and characters who will use some reasoning procedure to direct the conversation. There is a third option, often useful in IF with a fast-paced narrative: the character follows a conversational script, making sure to cover a series of points before the scene ends.
There are more and less tedious ways to implement this kind of scene. The worst case is one in which the player is not allowed to interrupt or ask any questions; he must merely wait until the character runs out of things to say. This can be useful and plausible in very small doses – say, two or three turns – but if the character has more information than that to impart, we may want to make the scene more interactive.
Pine 2 ★★★ partly addresses this challenge: the character has a line of conversation that she wants to follow to its conclusion; we may ask questions along the way, but if we're silent, she'll take up the slack, and the scene won't end until she's done with what she has to say.
Another kind of script is a series of actions for the character to perform. Robo ★ demonstrates a programmable robot that will observe what the player does, then try to emulate the actions later when switched into play-back mode. Robo 2 ★★★ extends this capacity to allow the robot to contain fifteen different scripts which the player can store, list, run, and erase.
Your Mother Doesn't Work Here ★ offers a character with a list of tasks but whose plans can be interrupted by more urgent demands. This verges on not being a simple script any more: if we carry the idea to its natural conclusion, we get characters capable of planning scripts for themselves to accomplish their aims. This is conventionally called "goal-seeking".
Goal-Seeking Characters for characters that work out plans for themselves in order to accomplish various outcomes.
Suppose the player's mother is supposed to be cleaning the living room, but she can be interrupted by the need to pick up things the player has dropped. New tasks are added to the end of her "current plan" list; every turn, she attempts to do whatever is the last entry on that list.
As goal-seeking goes, this is fairly rudimentary; "Boston Cream" provides an alternative (and slightly more sophisticated approach), but for really complex goal-seeking characters, it is probably best to turn to the character extensions designed for Inform.
So much, we had before. Now, suppose we want a conversation style which allows the player to move conversation forward by asking appropriate questions, but which will keep moving forward even if he doesn't. To this end, we provide a table -- a borrowing from a later chapter. In the table, we record two ways of performing each conversation bit, one which reflects the player's participation, and one in which the character moves things onward:
| topic | reply | quip |
| "dream/dreams/nightmare/nightmares/sleep" | "'Sleep well?' you ask solicitously. "'Ghastly nightmares,' she remarks. You nod politely." | 'Not really,' she replies, edging away from you. So much for that angle." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'So,' you say. 'This is a little weird since we just met, but, um. Would you like to get married?' "'I, er,' she says. 'I hope I'm not supposed to marry you or something.'" | She looks at you nervously. 'Do I have to?'" |
| "marriage/love/wedding/boyfriend/beau/lover" | "'I was told I was going to marry you and inherit the kingdom,' you say, apologetically. 'Would that be very bad?' 'Oh, it's not you -- I'm seeing someone,' she says, smiling quickly. "'Do you think I could go look for someone? I'm seeing him, you see, and I think I've been... sick... for a while, so he might be worried.' | You try to think how to point out that it's been a hundred years since she last saw her boyfriend." You try to think how to point out that it's been a hundred years since she last saw her boyfriend." |
| "marriage/love/wedding/boyfriend/beau/lover" | "'You've been up here for a hundred years,' you say. An unpleasant thought occurs to you. 'Was your young man in the castle somewhere?' "She goes to the window and looks out at the now-fading thicket of briar. 'That took a while to grow,' she observes. 'I've been up here longer than I thought.' | She shakes her head mutely." You shrug, uncomfortable." |
The "now Beauty is passive" line prevents her from making any conversation of her own on a turn when we've spoken to her. This keeps the conversation from progressing too quickly.
After we've generated any spontaneous conversation, we return her to her regular active state.
Now we have a scenario in which the player can ask her some questions out of order if he really wants to, but the scene will not end until the basic conversation topics have been exhausted. If we wanted to add some other chit-chat, not as part of the main conversation strand, but by way of optional enrichment, we might make a second conversation table and record alternative outcomes in it.
428. ★★★ Robo 2We have seen how we can make a robot that watches the player, then plays back the same actions again. A slightly more adventurous implementation would be to let the player create a whole series of named scripts which the robot will run on command.
To do this, we'll need each program to have a command that sets it off (stored as text, since this is the best way to capture and preserve arbitrary text entered by the player) and then the script of actions that must result:
Now, we want to let Robo learn new programs; for this purpose, we'll emulate the code from our previous implementation, so that Robo watches what the player does and stores those actions in his script:
Of course, we also need to be able to switch learning mode off, and store any script learned this way. We'll also use the same STOP command to make Robo terminate a program he's in the middle of running.
Next, we need to be able to play these programs back again. We'll give Robo a "current program" to store which program he's currently working on, and a number called "stage" which will record where he is in the script. Our previous implementation simply had Robo erase entries from his script list as he performed them, but this time we would like Robo to be able to remember and rerun the same scripts over and over, so we need something a little more subtle.
For the player's sanity, we should also provide a way to find out which programs Robo has stored in memory and what they do, so we design two listing commands:
And to complete the suite, in case the player runs into Robo's fifteen-program limit:
Now we use pretty much the same set-up as before to test Robo's abilities:
We could also have written this so that Robo learns new scripts by accepting the player's instructions, so that
…would store the script 'library theft' with the actions taking the book and going east. The implementation there would have been mostly identical, except that instead of an "after doing something…" rule, we would have captured commands as we asked Robo to perform them, and added those to the command list in progress. The alternative code might look something like this:
There are a number of ways we can make characters navigate our map. We might reasonably want them to approach and follow the player (as in Van Helsing ★★); or to allow the player to follow characters who have left the room (as in Actaeon ★★).
Characters who are less interested in the player will more likely follow their own courses around the available geography, however. A character may move randomly from room to room, as demonstrated in Mistress of Animals ★; he may follow a path that we have specifically written in advance, as Odyssey ★★ shows; or, most elegantly, he may use the "best route" calculation to find the best possible way to a given target room, as seen in Latris Theon ★★★.
This final method is arguably the neatest solution to character movement, allowing for characters to act in sophisticated ways; if we incorporate the Locksmith extension, other characters will even unlock and open doors that are in their way. The chief catch is that it should not be used too profligately with large numbers of characters, since on slow machines the processing power required to plan all their travel will make a noticeable difference to the running speed of the story.
All the same, the constraints are not so severe as to preclude having a moderate number of route-finding characters all wandering around at once. This does introduce a new problem, however: movement descriptions can become hard to follow if every turn produces long reams of reports such as
Patient Zero ★★★★ tackles this problem by calculating all of the character movement without printing any text; it then combines similar or related events into coherent paragraphs, as in
or
Doors, Staircases, and Bridges for some technical details of allowing other characters to interact with doors when they're in rooms that don't contain the player.
Suppose we want a restless sort of character always pacing from room to room. It is quite easy to use adjacency to achieve this effect:
Of course, it helps that Artemis is the sort to like open spaces. The implementation would become more complicated if there were doors which might block transit between these locations.
39. ★★ Van HelsingSuppose we want to write a character who tries to be in the same room as the player. We will do this by testing every turn whether the character's location and the player's location are the same; if the answer is no, the character will look for a path to the player's location, then try to move along that path. (We will learn more about finding paths and giving characters instructions later.)
The result will be that if the player ever moves to another location, the character will automatically pursue him.
In the following condition, we could also have written "if the location of Count Dracula is not the location", because "location" by itself is always understood to be the player's location. But it seemed better for clarity to write it this way:
Athena will proceed, unless delayed, through a list of locations stored in a simple table. Rather than using Inform's route-finding abilities ("the best route from…"), we simply move Athena from one location to the next, not even using the going action: she moves in mysterious ways, as befits a goddess.
| destination |
| Thebes |
| Delphi |
| Thebes |
| Athens |
| Corinth |
| Mycenae |
By blanking out the table line by line, we make sure that we never lose our place in the path.
Since we want the player to be able to talk to Athena, we need a way to stall her in her path, as well.
Finally, we do need to wake Athena up again if she has become passive. The following rule will occur after the movement rule just because of code ordering, though we could make matters more explicit if we needed to:
Suppose we want the player to be able to go after characters who are moving around the map. The trick, of course, is that once characters are gone they are no longer visible to "follow [person]", so we need "follow [any person]" to find them.
Here again the best route comes in handy:
We do also have to make sure that whenever we move a person from room to room, we record where they were moved from; otherwise, our clever restrictions about whom the player can pursue will not work properly.
To begin with, we create an action for going to a named place. All that this action will do is to change that person's hoped-for destination: the actual moving around comes later.
It stands to reason the player plays Zeus or at the very least Apollo, but let's not let this go to the player's head. Note that the following rule applies to the player, but not to anyone else, so HERMES, GO TO ATHENS will work but GO TO ATHENS will not.
And finally we recreate Greece and one of its heroes.
It simplifies matters that our map of Greece makes it possible to reach any location from any other location, by some sequence of movements: if there were an isolated location -- say, Crete -- with no map connection to the mainland, then we would have to worry about the "right direction" not being a direction at all. The following version of Hermes' trekking rule is protected against the possibility:
This is a light variation of a previous example, but we use it here because it is convenient:
| topic | reply | summary | turn stamp | character |
| "weather/heat/warmth" | "'It's appalling, isn't it? You'd think we didn't pay our taxes.'" | "that the weather is appalling" | a number | a person |
| "sun/sunlight" | "'Good thing the town mostly switched to solar power, har, har.'" | "that the town is mostly relying on solar power" | ||
| "rain" | "'Nope, there isn't going to be rain for 132 days,' replies [the noun]." | "that rain is not expected for another 132 days" | ||
| "snow/hail/ice" | "This hilarious sally is greeted with hoots of laughter only." | "that the concept of snow is downright laughable" | ||
| "disease/sickness/illness/syndrome" | "You get a cold, fixed stare in response. 'That's not funny,' [the noun] replies finally." | "that discussing the disease is more or less taboo" | ||
| "cold comfort" | "'If you haven't tried it, you should,' says [the noun]. 'Best ice cream in town, and that's saying something, you bet.'" | "that Cold Comfort has the best ice cream in town" | ||
| "town/city/village" | "'Yeah, it's a mite odd,' allows [the noun]. 'Not to everyone's taste, like...' [the noun as pronoun] considers for a moment. 'Like ginger ice cream. Big pieces of crystallized ginger... not everyone likes that.'" | "that the town is a mite odd" | ||
| "forecast/weatherman" or "weather forecast/man" | "'Oh, the weather man's gotten a lot more reliable since the gummint started making it for us,' says [the noun]. 'Now he just reads off the schedule on the air every morning. Pretty much takes the fun right out of the news, if you ask me.'" | "that the weather is all generated by schedule" | ||
| "taxes/tax" or "weather tax" | "A snort. 'You'd think for the rates we pay we'd get something a little pleasanter, don't you?'" | "that the weather tax really ought to be paying for something nicer than what you get" | ||
| "job/employment/work" | "'[if the noun owns a room (called the shop)]I own [the shop],' replies [the noun][otherwise]Work at the creamery, like most folk around here,' answers [the noun]." | "this and that about employment in town" | ||
| "book/books/reading" | "'The Public Library has a good selection, excepting only the cookbook section,' says [the noun]. 'That got censored way back when-- well, way back.'" | "that the Public Library has a good collection, except for the cookbook section" |
| topic | reply | summary | turn stamp | character |
| "ice cream" or "sorbet/sherbet/flavor/flavors/flavour/flavours/ice/ices" | "'The flavors are [list of flavors],' she responds promptly, without needing to draw breath." | "that the flavors are [list of flavors]" | a number | a person |
This strips 'the' out of the command, so that ASK PERSON ABOUT THE RAIN will be understood as well as ASK PERSON ABOUT RAIN.
Now we try something a bit unusual. Inform on its own will report each action on its own line, so that each character who walks into or out of a room will be described in a separate paragraph. This is usually fine, but in a game with a lot of characters moving around simultaneously, it can become a bit overwhelming. Instead, we may want to condense these reports into a single line, such as "Ben and Jerry enter from the south". The following accomplishes that goal by replacing some of the reporting rules, storing the information in a table, and then reading the table back later, once all the character movement has been resolved and the reports can usefully be collated:
| character | second | third | heading chosen | total |
| a person | a person | a person | a direction | a number |
| character | second | third | heading chosen | total |
| a person | a person | a person | a direction | a number |
| dipping |
| "looks as though dipped in" |
| "could have been rolling in" |
| "has a bad case of" |
| "suffers from" |
| "contracted a virulent" |
The next part could be simpler, but for rigor we will write it in such a way that it will work whether or not the serial comma is in use. This requires some extra work.
Because so much of this game is randomized, it will not be possible to provide a test command that systematically solves it. A good strategy is to go to Main Street, get the syringe; go to the Town Hall and get the key; then visit the shops, inject everyone, and lock them in when they've all been injected. Then go to the Pool Hall, turn on the air conditioner, and wait for the remaining parties to show up.
This is also something that could get fairly slow if we added many more rooms and characters to it. In that case, we might want to select fast route-finding so that character movement won't take as long. This will cost memory, possibly forcing the game into Glulx format if it isn't already, but significantly reduce the run-time for large maps with numerous people moving each turn:
Other characters can perform all the same activities that the player can; this does not always mean that they're willing to obey the player's instructions. By default, characters will refuse to obey commands of the form JULIA, WEST or ANTONY, TAKE THE PINCUSHION. Their objections can be overridden, however, and The Hypnotist of Blois ★ implements a hypnotist who can make characters obedient at will.
In For Demonstration Purposes ★★★, the character is only capable of a few actions at the outset, but can be taught new ones if the player performs them first.
Often we want characters' obedience to be more selective. Just as the viewpoint character may be characterized in terms of what he will and will not do, so may others: Generation X ★★ demonstrates a character who will do what she's told, but who will comment unfavorably when the player asks for a nonsensical or repeated action, and who may eventually get fed up and leave.
Characters can be given moral objections to certain commands, as well: Virtue ★ defines a few kinds of actions as bad, so that the character commanded will refuse to perform them.
Under Contract ★★★★, more subtly, has the character object if the player's commands implicitly require any behavior he considers inappropriate: for instance, if the player commands him to put his pants in a container, he will work out that this requires the removal of the pants as a preliminary. If we want to implement a similar character, we may want to simply copy his unsuccessful attempt rule and the table of his retorts, then replace his banter with lines of our choosing.
The little example Latin Lessons ★ allows us to make characters clever about vague commands: we can, for instance, write rules so that CLARK, EAT will have Clark sensibly pick something edible, rather than having the parser ask what we want Clark to eat.
Finally, Northstar ★★ demonstrates how we might make Inform understand commands of the form ASK JOSH TO TAKE INVENTORY or ORDER JOAN TO WEAR THE ARMOR.
Characters Following a Script for a programmable robot who can be given whole sequences of actions to perform.
We will learn more about check rules for other characters shortly, but the following prevents the hypnosis patient from trying to hypnotize us in turn:
If we're defining actions for other characters to follow, we may want to include them in our "rule for supplying a missing noun". We can do this if we write our "while…" clause to apply to any actor, as follows:
| cause | response |
| can't take yourself rule | "'Is that like 'get a grip on yourself' or something?' Jenna asks, momentarily diverted." |
| can't take what's fixed in place rule | "[physical impossibility]" |
| can't take scenery rule | "[physical impossibility]" |
| can't take what's already taken rule | "[already done]" |
| can't drop what's already dropped rule | "[already done]" |
| can't wear what's already worn rule | "[already done]" |
| can't take off what's not worn rule | "[already done]" |
| can't close what's already closed rule | "[already done]" |
| can't open what's already open rule | "[already done]" |
| can't switch off what's already off rule | "[already done]" |
| can't switch on what's already on rule | "[already done]" |
| can't unlock what's already unlocked rule | "[already done]" |
| can't lock what's already locked rule | "[already done]" |
| response |
| "'Did that,' says Jenna." |
| "'Check,' says Jenna." |
| "'Yeah, Mom, I already did that, okay?'" |
| "'Look, if I have to be here doing dumb stuff, could you at least tell me to do stuff that isn't already done?' Jenna asks wearily." |
| "Jenna gives a great upward sigh, riffling her bangs. 'Once again... there is totally no point.'" |
Most of the time, Inform understands commands to other characters when they take the form "JOSH, TAKE INVENTORY" or "JOAN, WEAR THE ARMOR". But novice players might also try commands of the form ASK JOSH TO TAKE INVENTORY or ORDER JOAN TO WEAR THE ARMOR.
The easiest way to make Inform understand such commands is to meddle directly with the player's command, changing it into the format that the game will understand, as here:
Note that we have to copy N back explicitly to replace the player's command.
239. ★★★ For Demonstration PurposesSuppose we want to have a character who can dynamically learn new actions by observing the player performing them. We could do this by adding the actions to a list of things the character can do, but using a relation to express the same idea allows for tidier, easier-to-read code.
Thanks to Jesse McGrew for the initial design of this example.
| cause | response |
| can't take yourself rule | "'I'm always self-possessed,' Clark remarks. You've heard that line before, but it sounds so much more convincing from him." |
| can't take other people rule | "'I don't think it would be appreciated if I tried to do that to [the noun],' he rumbles." |
| can't take component parts rule | "'I don't want to rip [the noun] out,' Clark remarks." |
| can't take people's possessions rule | "'I don't cotton to acting like a thief,' Clark replies. 'It ain't proper.'" |
| can't take what you're inside rule | "'Do you see where I am, babe?' Clark demands." |
| can't take what's already taken rule | "[already done]" |
| can't take scenery rule | "'I'm not the stunt man, darling,' he says with a wry twinkle." |
| can't take what's fixed in place rule | "'I'm not the stunt man, darling,' he says with a wry twinkle." |
| can't exceed carrying capacity rule | "Clark grins. 'I've only got so many hands, darling,' he says." |
| can't insert into closed containers rule | "[physical impossibility]" |
| can't go that way rule | "[physical impossibility]" |
| can't go through closed doors rule | "[physical impossibility]" |
| can't enter closed containers rule | "[physical impossibility]" |
| can't exit closed containers rule | "[physical impossibility]" |
| can't drop yourself rule | "'We're inseparable, me and me,' Clark replies, with a smile." |
| can't drop what's already dropped rule | "[already done]" |
| can't drop what's not held rule | "'Not under my control, [the noun],' replies Clark." |
| can't drop clothes being worn rule | "[salacious retort]" |
| can't put something on itself rule | "'I lack the dexterity,' says Clark. Oh, he's so modest." |
| can't put onto what's not a supporter rule | "'[The second noun] won't support a thing,' says Clark reprovingly." |
| can't put clothes being worn rule | "[salacious retort]" |
| can't insert clothes being worn rule | "[salacious retort]" |
| can't give worn items rule | "[salacious retort]" |
| can't wear what's not clothing rule | "'Costuming just gets stranger every year,' says Clark. 'In short: no.'" |
| can't wear what's already worn rule | "[already done]" |
| can't eat unless edible rule | "'What're you trying to do, poison me?'" |
| can't eat clothing without removing it first rule | "[salacious retort]" |
| can't take off what's not worn rule | "[already done]" |
| can't close what's already closed rule | "[already done]" |
| can't open what's already open rule | "[already done]" |
| can't switch off what's already off rule | "[already done]" |
| can't switch on what's already on rule | "[already done]" |
| can't unlock what's already unlocked rule | "[already done]" |
| can't lock what's already locked rule | "[already done]" |
| response |
| "'I have anticipated your every demand.'" |
| "'We've been through this part of the script already,' Clark remarks, with just a hint of creeping tedium." |
| "'Right right, already taken care of...'" |
| "'I'm a believer in rehearsal,' Clark says, sounding more bored than ever, 'but we really have got all this done already.'" |
| response |
| "Clark allows his mustache to quirk at the suggestion." |
| "Clark wiggles his eyebrows at you." |
| "'That kind of thing isn't in my contract, sweetie,' says Clark. 'If you're interested you'll have to ask off-camera.'" |
| "'I'd feel so... bare,' Clark says, with a sidelong look at you." |
| "'You first,' says Clark." |
| "Clark's stare is intense. You may be on the verge of breaking him." |
| response |
| "Clark frowns. 'I can't reach through things -- unless you were planning a special effect?'" |
| "'Look,' says Clark. 'If you want a stage magician, hire one.'" |
| "Clark just groans." |
| "Clark says drily, 'Is this in the script, or are we doing improvisation now?'" |
And now we make Clark a very amenable type:
There are quite a few actions for which no automatic other-character behavior is provided at all, because they always end in failure when the player tries them. Currently the response is not very interesting. Let's spice it up a bit:
And because we do not want Clark automatically taking off the pants as the result of a drop action:
We know that this can only come about as a default action, because we have arranged matters so that he cannot be persuaded directly.
Goal-seeking characters are the most advanced IF life-form: they want to achieve specific outcomes, and they are able to work out plans of approach in order to bring these things about. They walk to rooms, open containers to search for things, use keys and tools, and ask leading questions in conversation.
A really advanced implementation of goal-seeking behavior is beyond the scope of our examples (though extensions exist that treat the problem more thoroughly). We can accomplish a surprising amount without heavy customization, though, if we keep in mind three points of technique:
First: it helps to think abstractly and to create broadly-defined actions as a first step to more specific tasks. For instance, a character's goal might be to eat some dinner. He'd be equally satisfied with spaghetti carbonara or with braised lamb shanks, but he needs to figure out which is available. So we might have our every turn rule (or whatever we're using to activate the character) say something like
Dining would then be an action we've defined specially, which looks around Clark's environment for suitable food; if it finds food, it issues a
command; but if not, it sends Clark off to look for something likely. The Man of Steel ★★ demonstrates the use of this.
Second: though it doesn't actually contribute to the goal-seeking per se, lively reporting brings characters' generated behavior to life.
doesn't characterize Clark very much, even though the eating may be part of a subtle, intelligent plan to seduce Lois Lane. We'll do better if we replace a lot of the character reporting rules: to that end, see the example The Man of Steel Excuses Himself ★★.
Third: goal-seeking characters notice when something is in the way of the action they want to perform. When that happens, they form a plan about how to remove the obstacle. We've already seen this kind of implementation on the player's behalf: the player will pick up items before eating them, say. We can use Before rules to do similar things for other characters, as in
Here we've set things up so that if Clark tries to eat the wrapped candy, he'll be interrupted by this other command; and if his unwrapping-the-candy attempt fails, he won't go on and eat the thing. IQ Test ★ demonstrates a character who shows this kind of planning intelligence.
Because before-rules chain neatly, we can trigger whole plans of behavior if we have a sensible set, as in
We must exercise a little bit of care if it is possible for the chain of actions to produce an endless loop – e.g., the character trying to take a key that is inside the transparent, locked box that it opens might repeatedly try to open the box, first unlocking the box, first taking the key, first opening the box, … Boston Cream ★★★★ is a fully-worked scenario that deals with such a set of conundra.
Traveling Characters for characters who plan routes to locations and travel towards them.
Event Scheduling for characters who follow a pre-written schedule of activities.
Plot Management for having a central function direct all the characters in order to further the plot.
We have already seen how Before… rules can generate implicit actions for the player, so that the player will, for instance, open doors before trying to walk through them. The same can be done for characters other than the player; so for instance:
(A more detailed set of before rules for people using doors and locks is provided in Emily Short's Locksmith extension.)
203. ★★ The Man of SteelIt will sometimes be handy to write actions that are only available to the non-player characters and not to the player. To do this, we just define an action which has no "understand": the player will never be able to specify this command himself, but other characters can try it.
This is particularly useful for creating abstract or general actions for when we want a character to eat something, wear something, or go somewhere, but aren't too particular as to what the object is; as here, where we just want Clark to move away from the kryptonite, regardless of direction:
Report rules can be a good point at which to add local color: while Inform provides default descriptions of character behavior, these are rather generic and can stand to be customized.
For instance, if we wanted to liven up our previous Clark Kent example:
| reply |
| "needing a paper-clip" |
| "wanting an English-Tuvalu dictionary" |
| "walking a neighbor's dog" |
| "hearing air-raid sirens" |
| "having drunk too much coffee" |
| "thinking he smells smoke" |
| "wondering where Lois got to" |
| "needing to speak to Jimmy" |
| "noticing the Good Year blimp" |
It's good to be careful, as the library report rules have been designed and tested to describe every contingency (going through doors, going in vehicles, etc.): so when replacing a report rule, we should try to consider all the possible variations of the action that we might want to describe.
However, in this case, our scenario is so simple that there are no doors, vehicles, or pushable objects, so we're safe in giving Clark a very simple reporting scheme.
190. ★★★★ Boston Cream| failing | reply |
| can't take people's possessions rule | "'Ogg too polite.'" |
| can't take other people rule | "'Ogg not that greedy.'" |
| can't take scenery rule | "'[The noun] very very heavy.'" |
| can't take what's fixed in place rule | "'[The noun] very heavy." |
| can't drop what's not held rule | "'Hunh?'" |
Crowds of characters introduce new challenges, because we often want to show them interacting with one another, or to describe individuals in less detail when a whole group is present.
Strictly Ballroom ★★ gives us a set of characters who pair off each turn, making sure to mention each one once, and leaving one unfortunate person behind as a wallflower: this exemplifies how we might use a behavioral rule not to dictate the behavior of each individual separately but rather to model a whole group together. Happy Hour ★★ does calculate movements for characters individually, but then collates the descriptions, creating a single paragraph to describe whatever group is currently in the room.
Characters can also have complicated attitudes to one another, and it can be helpful to use relations to track these. Unthinkable Alliances ★ demonstrates the grouping of characters into alliance factions, while The Abolition of Love ★ provides a host of relations to track love affairs, marriages, memberships in families, and mere mutual respect.
Emma ★★ combines these two effects: its characters move between social groups depending on how they feel about the others in their particular talking circle, and descriptions change depending on who is where in the room.
Lugubrious Pete's Delicatessen ★ simulates a queue at a deli, in which the customers who most impress Pete get served first.
Traveling Characters for groups of characters who move around and have their movements collated into a joint description.
The following is best tested by experimentally kissing and/or attacking, and typing RELATIONS after every change to see the effect.
Suppose we are modeling a complex society seething with interpersonal relations of every kind.
Now we want ways to set and unset all of these relations. (In the interests of thoroughness, we may get a bit far-fetched here. It is not recommended in practice that we make the player guess the verb "traduce".)
Because love is a 1-1 relation, a person cannot love more than one other character at a time. Whenever we set a character to love a new person, that person ceases to love the character loved before. It is a fickle world.
One to various relations are a bit more open: we can say someone impresses multiple other characters, and our additions to the list do not override the initial ones.
And because this is a one-to-various relation, we can also make statements which set multiple relations at once, so:
Note that the above unsetting is not equivalent to "now the noun does not impress every person" -- which would be ambiguous in spoken English, as well. Various-to-one relations are similar:
Our options for setting and unsetting symmetrical relations are more limited again:
When we unset the symmetrical relation on one side, it is automatically set or unset on the other. It is not necessary to say "the second noun is married to the noun" or "the second noun is not married to the noun", even though that is the case.
And finally, setting groups:
Notice that when we say "the second noun is not related", we remove that person from the group: they are now in a separate group of their own, while the rest of the group's members remain related to one another.
And finally, a long litany of test cases, complete with the relations lists:
First, to set the scene:
Two processes compete here: one that fills the queue, the other which will empty it. The first process is the one which brings shoppers in to the counter, joining the back of the queue, which is where "add … to …" puts new entries by default:
The competing process is the one which serves shoppers and thus gets rid of them again: unfortunately, it is slower. But Pete is fair if inefficient, and serves the customers in strict order of arrival. Each served customer is removed from the front of the list, and the others therefore all move up a place.
That completes the example, but here is a variation to show that queues need not empty from the front. The Deli already looks a pretty sexist establishment, with the customers all being women, but it is about to get a whole lot worse:
We could then rewrite the service rule like so:
It is now heartbreakingly difficult for Alice to obtain her sliced chorizo sausage.
176. ★★ Strictly BallroomMany simple repetitions can effectively be done with a "now…" instruction: it is quicker to say
than
Repeat comes in handy when we have something a bit more complicated to do with each item:
Notice we did not say "repeat with dancer running through alert people who are not the player…". This is because Inform would draw up a list of alert people at the beginning of the repeat, and not take into account which people became occupied partway through the repetition. If we want to make sure that each person dances only with one other person, we have to continue checking alertness each time we run through the repetition.
After all the partners are assigned, we can set up for the next turn by making everyone alert again, and for this we do not need "repeat":
To start with, let's understand "room" to mean "a group of people talking". These groups can grow and shrink as people come and go, so we'll want to name and rename them; and we're also going to need some rules to motivate people moving around, and a description to narrate how they behave when we're with them.
And now we use writing a paragraph about… to describe character behavior in groups, when we join them:
Since this is just an example, we'll stop here, but there's no reason we couldn't write such paragraphs for everyone.
Often it is best to have an entire paragraph about the characters present in a room, but suppose we're narrating a large party with a lot of people moving around. In that case, it might be better to list everyone together, then add a few salient details by way of follow-up, like this:
The next part could be simpler, but for rigor we will write it in such a way that it will work whether or not the serial comma is in use. This requires some extra work.
And now the scene:
The vehicle kind in Inform refers to an object which can carry at least one person, but is small enough to fit into a single location:
We can then apply different rules to a player going somewhere on foot or in the vehicle. Peugeot ★ (a bicycle) is an easy example; No Relation ★ (a car) adds an ignition switch to the vehicle; Straw Boater ★★ (a motorboat) gets around areas of lake where travel on foot is not just slower but impossible.
Hover ★★★ (a sci-fi "hover-bubble") changes the appearance of the landscape when it is seen from inside the vehicle.
Ships, Trains and Elevators for larger conveyances.
Let's say that our protagonist is about to flee . Obviously, he can't make the journey on foot; he needs transportation.
We make the ten-speed bike a rideable vehicle because we want to say that the player is on it rather than in it. Then our other room:
And now we borrow from the Actions chapter to prevent travel without the proper equipment:
We need to designate certain rooms as roads. Since the status of being a road will not change during play, we do this with a kind:
(In the course of the writing of Inform 7, much of Trafalgar Square was pedestrianised, making this example already out of date.)
A further technical note: notice "going by a vehicle" in the above rule, rather than "going by something". A rule such as "Instead of going by something…" will be matched whenever the player tries to go some direction while in an enterable object, whether or not that object is actually capable of movement. This is sometimes useful, but in this case we want the warning to apply only when the player is in a vehicle; if we added Trafalgar Square's statue bases to the scenario, we would not want
So we restrict the rule to "Instead of going by a vehicle…"
49. ★★ Straw BoaterSometimes we like to give properties to kinds of thing, but not fill them in in all cases. For instance, we might have vehicles that optionally make noise, and those might have a "movement sound".
All properties have a default value, which we can find by looking in the Kinds tab of the index. This is what the property will be set to automatically, if we do not change it ourselves. In the case of a text property, that is ""; so for instance we might use our movement sound thus:
Note that we haven't given the sailboat any movement sound at all.
Suppose we want the player to see a modified room description when he's viewing the place from inside a vehicle. There are several conceivable ways of doing this; the example here shows a rather advanced way, but is very flexible and will let us write all sorts of special cases.
Here's the tricky part, which relies on material from the chapters on Activities and Rulebooks:
Now we've done that, we can write a "rule for describing the interior" of something, which will print whatever we like:
In fact, as a special refinement, we could even say:
And now anything that's beside us in the vehicle will be described during that first paragraph, rather than later on.
This section covers vehicles whose interior consists of at least one entire room. Moving into this room constitutes boarding: there is then some pause while it travels: moving out again disembarks at a different location. The only complication arising is how the player controls the journey (by talking to someone? by pressing buttons? by steering?).
The Unbuttoned Elevator Affair ★ provides the simplest possible whole-room vehicle, which ferries between two fixed points. If you are at one of these, it must be the other one you want to get to, so there is no need for controls.
Dubai ★★★ is a much more elaborate elevator, with many possible destinations, chosen using buttons inside the elevator.
Empire ★★ simulates a train journey. Here there are no controls as such, but the train passes through a sequence of stops spaced apart in time, so the player chooses an exit by getting out at the right moment.
On a very large, slowish craft such as a cruise liner, we are not so much travelling in a vehicle: it's more as if we are visiting a whole building, which becomes our world for the (probably long) duration of the journey. The liner steers around in long, slow curves, changing its orientation in the water, so that (if we think of "north" as a strictly magnetic matter, anyway) north is constantly rotating: something we don't notice on board because our own reference points, provided by the ship itself, stay fixed relative to ourselves. Because of this, some ships in IF are navigated using FORE, AFT, PORT and STARBOARD directions rather than NORTH, EAST, SOUTH and WEST: see Fore ★★★.
Bicycles, Cars and Boats for smaller conveyances.
This is very simple. The interior of the elevator is a single room, but which is mapped east of both of its termini. The reverse map connection, west from the elevator, can only go to a single room, and that's what determines which floor the elevator is on.
Suppose we want to have a train which, at fixed times, arrives at and leaves stations. It should be possible for the player to get on and off the train when it is stopped, but not while the train is in motion.
And now our schedule for the train -- somewhat truncated, admittedly, since the full three-day journey from Seattle to Chicago is a bit long even for an ambitious example.
Playing this out would of course require near inhuman patience. Let's set things up so that the player at least doesn't have to wait too long for his first departure:
…and provide fair warning of how slowly time is elapsing.
Suppose we want to understand shipboard directions, but only when the player is aboard a vessel.
And we can even add new ways to talk about the ways things are mapped, borrowing from the Relations chapter. The following will allow us to use "is abaft of" as well as "is aft of":
Now, to prevent the player from using NORTH onboard ship, or AFT on land:
The problem of implementing an elevator that opens onto a large number of floors often challenges novice interactive fiction authors. It also raises a fundamental design problem -- how to implement a large building in an interesting way. It is tempting to write a hotel with an elevator and innumerable tedious and identical floors just for the sake of realism; in many cases it is a better idea simply to omit any locations that contribute nothing to the story or the play of the game.
In charity, though, let us assume that the author has a legitimate reason for wanting to implement an elevator that opens onto some generic floors. We will go whole-hog, and set this in the world's tallest hotel: Burj al-Arab, Dubai.
(Since our budget did not run to visiting Burj al-Arab, the descriptions place implicit faith in the hotel's website.)
| level | floor |
| 0 | Al Mahara |
| 1 | Burj al-Arab Lobby |
| 2 | Al Iwan |
| 3 | Juna Lounge |
| 4 | Sahn Eddar |
| 15 | Al Falak Ballroom |
| 18 | Assawan Spa |
| 24 | Presidential Suite |
| 25 | Royal Suite |
| 27 | Al Muntaha |
This will all work very well, unless the player has portable objects; in that case, anything he drops on the Generic Floor will be there every time he goes back -- whether it's masquerading as Floor 6 or Floor 23. There are there are two ways round this -- (i) the cheeky way. When we drop something, the unobtrusive yet ever-vigilant maids pick it up and take it down to the Foyer's lost property office; and (ii) the super-duper way, in which things are moved out of play but with their floor numbers remembered, so that the scenario can be reconstructed each time. (i) is probably in fact the more true-to-life, considering the hotel's boasts about its service, but we will demonstrate both methods.
Here is the version with vigilant maids:
Notice that we tie the maid service to the pressing of the lift button, so that if the player just goes into the lift and comes out again, the maids will not have had a chance to clear his possessions.
Alternatively:
The "enclosed by" line clears even things left on, say, small un-portable side-tables or whatever; but because we do "in" first, we make sure to move any containers or supporters undisturbed. The next bit could be more tidily incorporated into our previous "before going outside" rule, but since we are writing this code to be optionally pasted onto the end of the first bit, we'll express the rule separately:
And now we have a situation in which the player's valuables are left untouched wherever in the hotel he happens to abandon them.
Incidentally, this example was almost set in an entirely different location: the largest hotel in the world may some day be the Ryugyong Hotel in Pyongyang, North Korea, with its 105 floors -- but for some years construction halted at the creation of the building's huge concrete shell.
Animals exhibit a wide range of behaviour: much of the chapter on Other Characters applies just as well to animals as to human beings, with the exception of the material on conversation. But two examples here, both fairly simple, show how a fairly convincing domestic pet can be achieved simply by reacting to certain events going on nearby: Feline Behavior ★ (a cat) and Today Tomorrow ★★ (a dog).
Fido ★ provides a dog which the player can re-name at will.
For animals that we can sit on and ride – a camel or a horse, say – we may want to use the Rideable Vehicles extension by Graham Nelson, which also provides a rideable animal kind.
Liveliness for pets that change what they're doing every time the player looks.
Bags, Bottles, Boxes and Safes for a cat that eats food put in its container.
Suppose we have a cat which is supposed to react to (and destroy) the most interesting thing in its environment. There are several ways we could approach this problem, but for the sake of demonstration, let's have it follow a rulebook to figure out which thing it most wants to interact with. We will then return the chosen object as "the object produced by the cat behavior rules".
We include the if rule succeeded… condition here because nothing will be returned if the cat's search failed (as for instance in the result of the final rule).
Naturally, if we wanted we could equally well ask "if rule failed…".
419. ★ FidoSuppose we'd like to have a dog which the player is allowed to name himself. We'd like to deal correctly with both
and
so we'll also need to strip quotation marks out of the command. We can do this as follows:
Rules about concealment will affect "in the presence of", too. For instance, suppose we have a man with a pocket pet:
Unless we somehow get the trenchcoat away from Maya, the chihuahua will not be in view, and will not intervene in our lunch. All very well for the player character, but not so interesting to the story… To this end, we might add an unfortunate event, courtesy of later chapters:
Most domestic furniture consists of supporters and containers of one size or another. This means that the simplest furniture needs no elaborate instructions:
The examples below are therefore mostly ways to get around the usual restrictions on containers (that they only have one interior) and supporters (that they cannot simultaneously be containers as well).
Yolk of Gold ★★ provides a set of drawers, that is, a container with multiple interiors.
U-Stor-It ★★★ provides a way to have containers with a lid which is also a supporter.
Swigmore ★★ provides a supporter which holds up the player, but has no top surface as such, and cannot hold up anything else. Kiwi ★ demonstrates a kind of high shelf, whose objects cannot be seen or used unless the player stands on a ladder.
Princess and the Pea ★ shows how a pile of supporters, each on top of the last, could be managed.
Tamed ★ demonstrates furniture large enough to get inside, or on top of.
Circle of Misery ★ demonstrates a conveyor belt, which can hold multiple items but only brings one of them within the player's reach at a time.
Position Within Rooms for a box that can be positioned and used as a stepping stool.
The Human Body for letting the player take different postures on furniture or on the floor.
Room Descriptions for tables and other furniture whose content listing is suppressed or modified in a room description.
Entering and Exiting, Sitting and Standing for making the player automatically rise from a seat before leaving the room.
Clocks and Scientific Instruments for a grandfather clock.
Kitchen and Bathroom for a mirror the player can look into.
Within a room, we might have containers and supporters that a player can enter. A chair, stool, table, dais, or pedestal would be an enterable supporter (anything we would describe a person as being "on"); a cage, hammock, or booth would be an enterable container (because we would describe the person as being "inside").
When the player is in or on something, he is able to see the rest of the contents of the room, but a note such as "(in the hammock)" or "(on the poster bed)" is added to the room title when he looks around.
Here is an example to show off the possibilities:
Notice that we made the cage transparent. Strictly speaking it is not made of transparent materials, but we can see into (or out of) a closed cage due to the gaps between the bars, so that from Inform's point of view a cage behaves much like a large sturdy glass box. (If we really wanted to make a distinction between, say, an airtight container and one with perforations, we could do so, but Inform does not model such nuances by default.) If a container is not transparent, we can see into and out of it only when it is open.
Supporters are a bit more straightforward because there is no circumstance in which they separate the player from the rest of the world:
And in fact we can tell Inform that the player starts on the pedestal with this line:
Now the player will begin there rather than just in the Center Ring.
This last bit is an entirely unnecessary bit of local color, but if we're going to keep getting into and out of the lion's cage, we ought to expect him to take notice:
Randomness is explained more completely in the chapter on Change, and every turn rules in the chapter on Time.
Finally, we might want a container whose interior is modeled as its own separate room: say, a magician's booth in which volunteers are made to disappear.
Now we create our other location:
…which handles the case of the player typing >IN. (We will not assume by default that he wants to get into the cage with the lion, this being obviously perilous.) But we also want to make sure that the player who types >ENTER BOOTH winds up in the same place, so we should add:
The main point here is that we need to figure out where the stack meets the floor:
Suppose we want there to be some high shelves in our game, which the player can't get at unless he's standing on a prop of some kind. (This is a pretty hoary and over-used puzzle, but there may still be occasions when it becomes useful again.)
In order to resolve this, we want to set up a raised supporter kind. When something is on a raised supporter, it should be mentioned to the player only if the player is in the right position (i.e., standing on something) and otherwise omitted from the description entirely.
Note that here we don't continue the activity because we want to completely replace the normal behavior of describing what is on supporters.
Now we also need to prevent the player from interacting with things that are out of reach:
…or restoring things to the shelves while the player is in the wrong position…
And raised supporters shouldn't be searchable from the ground either:
Finally, we need to tackle the case where the player types GET ALL FROM SHELF, because we don't want to list the objects up there if the player can't even see them. We use a rule for deciding whether all includes in order to tell Inform not to consider items that can't be reached, and then we adjust the parser error so that it's a little more instructive than "There are none at all available!", which is what the response would otherwise be:
The only point we need to be careful about is that the carousel is simulated twice over, in the following text: once in the built-in way that objects are inside other objects, so that the luggage items are objects contained in the carousel object; but then again by the "circle of misery" list, a ring buffer keeping track of what order things are in. We need to be careful that these two records do not fall out of synchrony: anything put into the carousel must be added to the list, anything taken out must be removed. (In fact we forbid things to be added, for simplicity's sake.)
The list "circle of misery" is our ring, in which entry 1 is considered to be the position of whichever bag is currently frontmost. And here it goes, round and round:
Suppose that for dramatic effect we would like the player to find the thing he is looking for always in the last drawer he opens…
Perhaps, just for fun, we have all the other scenery draw the player's attention back to the main point, as well.
Inform's default assumption is that if a player on an enterable object drops something, the dropped article winds up beside him on the same supporter or in the same container. This makes lots of sense for a dais, say, or a king-sized bed. It's a little less sensible if the enterable supporter in question is a bar stool or the like. So suppose we want to add a new kind of supporter called a perch, where everything dropped lands on the floor.
There are actually several ways of implementing this, but one of them is to reach right into the drop action and replace the "standard dropping rule" with a different one of our own invention -- like this:
Now the carry-out behavior of the dropping action has been changed, but we haven't had to interfere in the checks or reporting at all. The rest of the action works just as it always did.
Of course, maybe we do want to change the way the action is reported, to make it clearer to the player where the dropped article wound up:
Suppose we want to write a game in which there are a number of chests. Each of these chests will be a container, but have a lid which is a supporter.
(The "specification" of a kind is not really a property, and is used instead to describe the kind in the Index. So the text of these specifications is never found in the game.) Of course, this doesn't get us very far. We will also want the game to correctly interpret variations on "open the chest" and "close the lid", redirecting actions appropriately.
We may also want to be able to deal with "put in" and "put on" appropriately, even if the player names the wrong part of the object:
Furthermore, we don't want the player to be able to put things on the lid while the chest is open:
And then we may also want a couple of rules for describing our assembled object nicely:
Now we are free to create entire treasure rooms at a single blow:
Even though we have never explicitly defined it, the metal box has a "metal box's lid", which we can use at need.
Before implementing elaborate mechanisms to handle plumbing, we should pause to ask ourselves: how much of this do we need? Is it really necessary to simulate the complete set of fixtures and fittings?
This turns out to be a little tricky to do, and also rather dull to set out. The example Modern Conveniences ★★ was actually written as a demonstration of how an extension to Inform might be written to provide a general "kitchens and bathrooms service" for writers, but it contains a nice implementation well worth borrowing. The idea is to provide a "kitchen" kind of room and a "bathroom" kind of room. All kitchens created automatically contain standard kitchen appliances: fridge, freezer, sink with taps, counters, cabinets, and a stovetop with built-in oven. Similarly, all bathrooms will have sinks, baths, cabinets, and toilets, and respond to some standard interactions.
Another common feature of bathrooms is a mirror: Versailles ★★ demonstrates how to create a simple one.
One of the advantages of descriptions is that we can use them to pick an item randomly from a specified category. (For more on this possibility, see the Change chapter sections on randomness.)
For instance, suppose we wanted to create a mirror in which the player would see some item from the room reflected. We might write
This is the same as "a random thing which is in the location": phrase "in…" can be used briefly in Inform as it can in English.
But, on a little more thought, we might want to expand on this: the mirror perhaps should reflect not only things that are in the room, but anything that the player can see (even if it's on a supporter or carried by someone). So then we might instead write
There's still a risk, though, that this will produce the response
because, of course, the mirror is itself visible. So instead we might write
A final note: we use "searching" here because Inform understands both SEARCH THING and LOOK IN THING as the searching action, and the player is most likely to type LOOK IN MIRROR in order to see the reflection there. In the absence of an example, we can discover the relationship between actions and their command vocabulary in one of two ways. A complete list of actions and the vocabulary associated with them is available in the Actions index. Alternatively, we can type ACTIONS at a prompt, followed by LOOK IN MIRROR, and get the response
…which tells us that Inform is understanding the action as "searching the mirror".
448. ★★ Modern ConveniencesSuppose we want to write an extension or other portable code which defines a "kitchen" kind of room and a "bathroom" kind of room. All kitchen rooms we create in the future will automatically contain standard kitchen appliances: fridge, freezer, sink with taps, counters, cabinets, and a stovetop with built-in oven. Similarly, all bathrooms will have sinks, baths, cabinets, and toilets, and respond to some standard interactions.
We would do this with a standard assembly:
Now: we're going to want many of the items in our kitchen to have switches, and to handle input sensibly regardless of whether the player types TURN ON STOVE or TURN ON STOVE SWITCH. (This is apparently a stove with only one burner.) For convenience, we'll define an "includes" relation:
What follows is fairly straightforward, but notice that we are somewhat obsessively naming every rule. This is much more important in extensions (where someone else may need to manipulate our code from within their own source) than it is when we are simply composing source text for ourselves.
This is probably about as far as we want to go in a generic simulation: it is tempting to code up water, drains down which the player can lose objects, sinks that get clogged and overflow, and so on; but the more we embellish in these ways, the more likely the end result would be disruptive to individual games. For right now what we're aiming for is something simple which provides the basic interactions a player might expect in this kind of room, but which does not have any significant implications for the surrounding world model.
A particularly conservative author might even want to make it turn out that the water has been shut off and nothing flows from the taps: in the extension documentation, we might want to include a line or two of example showing how this might be done by changing or removing the relevant rules of our extension.
If we were feeling particularly ambitious and inclined toward interior decoration, we could add bath mats, mirrors, plungers, toilet brushes, overhead lighting, towel racks, scented candles, boxes of facial tissue, shampoo bottles, scrubbing loofahs, etc. ad nauseam; but we'll keep it relatively simple for now. Of course, if we have a toilet, we pretty much have to accept that the player will try to make use of it:
Now we might put this to work in a short example.
One slight challenge lies in giving these assembled pieces separate descriptions. When we have an assembly that adds parts to objects, we can then talk about (for instance) "the stove's switch" elsewhere in the code. But items that have been assigned rooms are not named in the same way, so we cannot talk about "the Industrial Kitchen's stove" in our code as a way to assign it a description or special behavior. In quite a simple example, we could make the descriptions of the kind simply be the descriptions we want for the individual items:
In a game that featured multiple bathrooms and kitchens, this wouldn't be enough; our author might give the stove kind (say) a description that checked its location, as in
or create an
sort of rule for those objects he wanted to describe specially; or he might use a when play begins rule to initialize a few things:
Or we might even (if we anticipate lots of these kinds of amendments) want to rig up something more complex that finds the descriptions of appliances in a table, rather than relying on their individual description properties. This can all be done, but it is only interesting as long as it remains genuinely labor-saving: that is, as long as the convenience of having the assembly is greater than the annoyance of writing special rules to cover for the automation. In the end, the "kitchen" and "bathroom" room types are likely to be most useful for authors who want to include the standard props but not actually make them a critical part of the game; if stoves and sinks have more of a starring role in the production, authors may be better off coding them or at the very least placing them by hand, as in
All these quirks are things that we (as the extension author) want to think out in advance: we should ideally warn authors about possible pitfalls in using our extension (if we can think of them) and point out ways of customizing the behavior (if there are interesting ways).
Inform provides an either/or property called "edible" and an action, "eating", for consuming edible things:
For eating something not immediately to hand, see Lollipop Guild ★★★. Delicious, Delicious Rocks ★★★, conversely, adds a sanity check which prevents the player from automatically taking inedible things only to be told they can't be eaten.
Inform does not normally simulate taste or digestion, but to provide foods with a range of flavours, see Would you…? ★; to make eating different foods affect the player differently, see Stone ★, or for the extreme case of poisoning foods, Candy ★. In MRE ★, hunger causes the player problems unless he regularly finds and eats food.
Liquids for things to drink.
Dispensers and Supplies of Small Objects for a pizza buffet table from which the player may take all the slices he wants.
For instance, if we want to give some objects a flavor:
Things are, in general, not edible by default, so we have to make them edible specifically in order to allow them to be eaten by the player. Here we've defined food to be edible by default, and we have given it a standard piece of flavor text.
Note that we use "if the noun provides a flavor…" to make sure that the property exists before attempting to use it. Otherwise, there is the risk that we will try to print a property that does not exist, resulting in errors in the game.
We will only get the "It's [noun]-flavored." response if we successfully eat something that is not a food and does not have flavor text. To test this feature, let's suppose something that isn't exactly food but can theoretically be chewed on:
Suppose we want to give the player a bag of candies, of which a random one is poisonous. We can pick which one should be poisoned at the start of play, like this:
Many older interactive fiction games required the player to find food and eat on a regular basis in order to avoid death. This effect was often unrealistic (since most people can survive much longer than a few hours without eating) and is often seen as an annoyance. However, for the sake of argument, suppose that we do want to construct a hunger-and-death system.
To make things a little more interesting, we will postulate that different foods are differently filling, so that if the player manages to find something really caloric, he is off the hook on his hunger search for a while.
We will also implement the system so that the player gets messages when he is hungry, then dies a short time later. (The times involved are ludicrously short, but this allows us to see the effects within a simple example. In a real game we would want to allow a considerably longer timer for the hunger to play out.)
First, a little scene-setting:
Now we define our food, and add some special instructions for what happens to our hunger counters when the food is eaten:
The first of those two phrases, "now the player is replete", causes the player to cease to be hungry; the second one sets up a future event in which the hunger sets in again. The length of time until that event depends on how satisfying the specific food is. Now we define that event:
Note "if the player is hungry": it is possible that the starvation event will be set up but the player will eat before it occurs; in that case, we want it not to take effect.
And now, since we really ought to give the player some warning of what is happening to him:
| hunger |
| "Gosh, you're starving." |
| "It feels as though you haven't eaten in days. Weeks, almost." |
| "The world seems to slow down and everything becomes sharper and brighter. You are a hunter, a hunter of foodstuffs." |
| "You find yourself staring at [the random visible thing that is not the player] and wondering how it would taste." |
A thing can have a rule as a property, if we like. Here we are going to allow the player to make a soup whose effects will depend on its ingredients. Each ingredient will have its own "food effect" rule, to be followed when the food is eaten.
Note that there are other, slightly less cumbersome ways to do the same thing -- we will see in the chapter on Rulebooks that we could make a "food effects rulebook" and then write a number of rules such as "food effects rule for carrots" or "food effects rule for the stone". Nonetheless, we demonstrate rules-as-properties here for the sake of thoroughness.
So:
And now to provide some particular foods:
And the following is a relatively unimportant nicety:
In some cases, we may want to add new stages to action processing. One possibility is a stage where we check the sanity of what the player is trying to do before executing any of the other commands; so that we avoid, for instance
Here is how we might insert such a stage in our action processing, using rulebook manipulation.
Notice that now Inform does not try taking the rock before rejecting the player's attempt to eat it.
It is of course possible to get the same effect with
…and in a small game with few rules, there's not much reason to add an extra stage. The ability to modify the stages of action processing becomes useful when we have a fairly large game with sophisticated modeling and want to be sure that some kinds of message (such as the sanity-check) are always handled before other things that we might be doing at the before stage (such as generating implicit actions like opening doors before going through them).
The kind "container" allows one thing to contain others. Things are sometimes containers automatically, sometimes by instruction:
The matchbox, like the bucket, is a container. Containers come in all sizes and have a variety of behaviours, mainly controlled by the properties we give them: they can be "open" or "closed", "opaque" or "transparent" (when closed), "openable" or not, "lockable" or not, "enterable" or not. The basic ideas of containment are to do with carrying and sometimes hiding the contents, and Inform makes this easy. Allowing for locking and unlocking is again straightforward:
Two built-in extensions enhance and modify the behavior of locks and keys: Locksmith automates a number of steps, automatically unlocking doors when trying to open them (for instance). Skeleton Keys allows us to define multiple keys that unlock the same object, rather than being restricted to one matching key per item.
For a container with a combination lock, rather than a key, see Safety ★; for a more sophisticated safe requiring digits dialed over multiple turns, see Eyes, Fingers, Toes ★.
Trachypachidae Maturin 1803 ★★ provides a bottle that is stoppered with a cork: when it is closed, the cork is part of the bottle, but otherwise the cork becomes a separate object we can carry around.
The normal assumption is that there is no problem with any two portable items being carried together, but in reality they may affect each other. (For effects like magnetism, or getting each other wet, or setting each other on fire, see the Physics chapter.) Here is a cat which, if boxed up with one or more items of food, will eat something each turn until all is gone:
The examples below provide subtler effects, adapting text to the current situation. In Cinco ★, the container's name changes depending on what it contains: putting beef in a taco allows the player to call it a SHREDDED BEEF TACO. In Unpeeled ★ and Shipping Trunk ★, the description of something inside a container changes according to other things are alongside it. This is taken further in Hudsucker Industries ★★, which describes the contents of a container as a group.
Finally, any action that destroys a container has to consider what to do with the things inside. Fallout Enclosure ★★★ demonstrates a zapping action that destroys cash registers and shelves but leaves their contents tidily behind.
Liquids for a SHAKE command that makes containers rattle when there are contents.
Glass and Other Damage-Prone Substances for opening containers by cutting into them.
Fire for fire damage that spreads between containers and their contents, leaving fireproof objects intact.
Volume, Height, Weight for containers breaking under the weight of their contents.
Heat for keeping things warm in insulated containers.
Furniture for chests with lids that can support other objects.
Modifying Existing Commands for ways to allow the player to unlock with a key he isn't currently holding.
It's fairly common that we want to be able to refer to a container in terms of what it has in it: a bottle of wine, a salt shaker, a chicken sandwich. The player is free to remove the contents again, and the object will go back to using its usual name:
First to lay some groundwork:
And now, with that preparation:
It is not difficult to implement a safe which can be set to a single number to open; but a more common scenario in the real world is for the safe to open on a sequence of numbers when they have been dialed in the right order.
For IF, this means that we have to keep running track of the last N digits the player has dialed, dropping the first digit and adding a new one to the end each time the player re-dials the safe. This is a perfect occasion for lists:
In this scenario, the player starts with a bag full of unsorted letters. These can be polite or rude, but he won't know which until he has examined them. What's more, he is allowed to sort the letters, in which case a group of letters will be shown as (for instance) "two polite letters"; but a group of mixed letters, even if they have all been read, will be called "unsorted letters".
Further, the player should be allowed to refer to sorted letters by tone, but not unsorted letters.
To do this, we'll need printing the name… and printing the plural name…, as well as some special understanding rules.
Now, there's a good bit of interaction to streamline. We intend that the player will be taking letters from the satchel, reading them, and putting them (perhaps grouped) into boxes. Our interaction rules should assist in this process as much as possible. To start with, the player will be most likely to examine letters he hasn't read yet:
The rules about taking are more subtle: the player is more likely to want to take an ungrouped letter than a grouped one; he is more likely to want one from the satchel than not; and he is most unlikely to want to take a letter (grouped or ungrouped) that he is already holding.
And finally, we will assume by default that anything other than examining or taking is most likely to apply to a letter he's already identified:
And we would also like to understand properties under the same circumstances as printing -- a letter will be identifiable as "polite" if it's already been read and it is either by itself or in a sorted stack of polite letters, but otherwise not. What's more, to make it possible to disambiguate commands in the other direction, we'll call any unsorted letter "random", to represent that the player doesn't know what it is.
That last "repeat" is merely a device to shuffle the order of items in the satchel so that the player will not always encounter the letters in a neatly presorted order, despite our defining them that way. (Of course, that means that the test produced by TEST ME cannot be very exciting…)
35. ★★★ Fallout EnclosureIt may not be immediately obvious why we might want to create new intermediate categories of the kinds hierarchy. But there may be times, for instance, where we would like to make an action that applies in the same way to both containers and supporters, but to nothing else in the game. To avoid creating two nearly-identical rules, we would instead roll the two categories together into one, on the principle that duplicating source text is usually a sign of bad design.
So for instance let's say the player is able to zap objects to make them go away, but any contents -- things inside a container or on top of a supporter -- should always be left as residue. Here's one way we might do this:
A person can wear any (portable) thing which has the "wearable" property. (This property seldom needs to be quoted because it is deduced automatically from sentences like "Trevor wears a red hat.")
In most traditional IF, clothing is only used when it is exceptional in some way. That is, we ignore the three to eight different garments most people are wearing at any given time – the everyday clothes which people wear without thinking about them – and only simulate the unexpected extras: a borrowed jaunty red hat, a radiation-proof space suit, and so on.
These unusual garments turn up only occasionally in play and usually one at a time, so Inform does not normally provide rules to restrict how much or little is worn, or in what unlikely combinations. Get Me to the Church on Time ★★★ categorises clothing by body area (trousers for lower body, shirts for upper); Bogart ★★★ by layer, distinguishing underwear from outer garments. What Not To Wear ★★ combines both into a general-purpose system adequate for most kinds of clothing situations.
Hays Code ★ is a somewhat stripped down version.
Clothes are normally single things which have no function other than display and concealment, but Being Prepared ★ gives them pockets which act as containers, and Some Assembly Required ★ allows clothes to be stitched together from pieces of cloth.
Kitchen and Bathroom for a simple mirror implementation, which could be adapted to reflect what the player is currently wearing.
Now we've created the rules that will govern any specific jackets we might happen to put in our game: each one will always have one pocket, which will be able to contain no more than two things. The description of "a list of things" is text with a list, which we will learn about further in a few sections.
Next we might want to create the environment and an actual example of the jacket kind:
Notice that, since Inform has created a pocket for the hoodie, we can now refer to it by name in our source, giving it any additional properties we need to define. Here we simply put a few items into it.
Notice that Inform automatically refuses to put the hoodie into its own pocket: as a default, a container cannot contain something of which it is itself a part.
332. ★ Some Assembly RequiredWe now have the mechanisms in place to do some fairly sophisticated renaming of objects. For instance:
Here is where the issue of precedence arises. We want to encourage Inform to select a cuttable object that is part of something else, rather than one of the spares:
The following burlesque was considered too much for the tender readers of Chapter 3, since it involved explicit use of listing and persuasion:
We start by borrowing some of the same ideas from the Bogart example, but we're also going to make a kind called "garment-element". This kind will include both garments (objects of clothing) and body parts (things that can be covered by clothing); using it allows us to restrict the way our underlying and overlying relations apply, which will make them a bit faster at run-time.
Here we've expanded on the previous ideas of 'uppermost' because it is possible for an upper layer to reveal what lies beneath: a tie, a clear plastic trenchcoat, an open-knit sweater, etc. We'll make such items transparent.
Here we draw in the idea that different clothes go over different areas of the body, and that they should be in competition with each other only if both sets of clothes belong at the same level over the same body area.
This may seem like overkill, but it allows us to create garments that cover different subsets of the body -- pants and shirt vs. a dress, for instance.
To help with modeling, we'll give everyone body parts, broken down according to their relevance to clothing:
If we wanted to allow gloves, we might put in hands as well; but this is enough for now.
And now we make some categories of clothing:
Inform's default handling of wearable things does not make any rules about what can be worn together. Suppose, however, we have a game in which there are a large number of different garments, and we want to keep the player from wearing (say) more than one pair of pants at once:
And now the rule itself, borrowed from a later chapter:
If we wanted to, we could make similar kinds for hats, shoes, and so on, and have a simple but effective system of clothing. A more complicated treatment might keep track of layering and describe the player's outfit differently depending on which clothes were outermost -- an example for a later chapter.
234. ★★★ BogartWe have two things to keep track of with our layering clothing: what currently is covering something else; and what can cover something else. This implementation goes for a fairly simple treatment, assuming that each item of clothing will completely conceal those beneath it, and that we are not implementing entire sets of shirts, jackets, etc. But it will do for a demonstration.
First we make our relation to represent what *is* underneath another item:
And now we prevent taking a lower layer off before the thing that is worn over it:
That covers order of clothing removal, but we also want to restrict what can be worn on top of what else. This time we need Inform to have some idea of what customarily can be layered on top of what other clothing:
With these definitions, we can say that a jacket should go over a shirt and a shirt over an undershirt (say), and then Inform will know that a jacket will cover both shirt and undershirt.
Notice that our inventory only describes the things that the player can see as the upper layer of clothing.
If we further wanted to prevent the player from taking off clothes in inappropriate places, we might add something like this:
Money could be anything which the two people in a bargain both agree is valuable. Here, the player and an ogre agree on a copper coin as money:
Now Inform does provide an action, "buying", and a command for it, BUY, but they ordinarily respond simply "Nothing is on sale." This is no longer true, so we should make BUY CAKE work. The difficulty here is that a command like BUY CAKE does not specify what should be handed over in exchange. Here we just check that the player has the coin, but in principle we could check for any of a range of monetary tokens – coins, notes, cheque book, debit card, and so on.
In more advanced economies, where shopping replaces barter, the seller will stock a wide range of differently priced goods. For a tabulated catalogue of wares, see Introduction to Juggling ★★★: to allow the player to negotiate prices, see Money for Nothing ★★. In both of those examples, the player's current financial worth is simulated only as a current total amount of money carried – say, $2.50. This is typical, because in most situations what matters is how much money is in the pocket, not how it is made up. Money behaves more like a liquid than a set of items: hence terms like "liquidity", "cash flow" or Frozen Assets ★ – the name of the simplest example demonstrating this. If we really need a comprehensive simulation down to pieces of currency – where it makes a difference carrying four quarters rather than a dollar bill, because the quarters can be fed into a vending machine – see Nickel and Dimed ★★★.
Fabrication ★★ takes the problem in a different direction, making calculations about the cost of a new garment based on the price of the pattern, the quantity of fabric required, and the value of the fabric type chosen -- showing off what we can do with unit multiplication in Inform.
Widget Enterprises ★ explores the challenge of pricing widgets for maximum profit, given certain necessary costs and customers with varying willingness to pay.
Actions on Multiple Objects for an implementation of giving that allows the player to offer multiple objects at once, where their combined value determines whether they are accepted.
Suppose the player is responsible for pricing at Widget Enterprises. Widget production entails a certain fixed cost as well as a cost per unit; and somewhere out in the world there are a number of customers interested in purchasing widgets, but the player starts without knowing what this distribution looks like.
We can express the profits as an equation: the total made by selling widgets, minus the cost thereof.
The Table of Customers holds the data about customer preferences, and whenever the player selects a widget price, we consult it to determine how many customers in total would be willing to buy at that price.
| base | maximum value |
| 2 | $26.00 |
| 5 | $20.00 |
| 8 | $15.00 |
| 2 | $13.50 |
| 1 | $9.00 |
As written this will be a rather dull guessing game for the player; more interesting would be to enhance it into a fuller economic simulator with more control over fixed costs and customer price points.
264. ★ Frozen AssetsIn our brave new world, everything will have a price, so we had better spell this out.
Now we assume a simple shopping model in which the player can't take anything without paying for it.
The player's money object is going to be a bit unusual, because it has value but cannot itself be bought.
Now we just need something to buy.
Implementing caloric units for this scenario is left as an exercise for the reader.
265. ★★ Money for NothingNow, since the man does make counter-offers, it would be reasonable to let the player accept or reject those, as well:
And we borrow just a line or two from a later chapter to take care of some alternate syntax the player might try:
When we make a new kind of value, the new named values can themselves have properties. That is convenient because, for instance, we might want to associate a material (itself the property of an object) with certain features, such as price.
Typically games which keep track of the player's wealth need only do so as an abstract number, but occasionally it becomes useful to represent money as physical coins and bills. Here is an example that does exactly that:
Our choice of understand rules guarantees that "five dollar" will be understood as the five, but "dollar" alone as the single. We will learn more about "understand" in later chapters, but here is a test to check the functionality:
The cashbox is a theoretical construct, not something the player will ever encounter in the course of the game. It contains all the money that is available for non-player characters to use in making change. If we wanted, we could give each character his own stash of change, but this would increase the likelihood that any given person would run out of cash to make change with. (And in this example there is only one vendor anyway.)
We've skipped over defining what makes a denomination the best for a given transaction, so we'd better do that now. Our goal is to avoid ever having the player gratuitously overpay -- he should always offer the smallest amount of money that will meet the price of what he's buying.
We also assume that all money "enclosed by the buyer" -- that is, somewhere in the buyer's possession -- is available for use. This might not be true in a game where the player could pick up, say, a sealed lucite container with a ten-dollar bill inside; in that case we would have to define our terms more rigorously, perhaps by requiring that the bills be both enclosed and touchable by the buyer. The touchability check adds an extra layer of calculation, however, and since it is not necessary in this example (and probably not in most other cases either), we'll leave it out:
Notice the "say underpayment/overpayment section…" noted out, above. This is for debugging purposes: when writing complex code, it is sometimes useful to put in lines that will say explicitly what is going on. We can enclose them in brackets and Inform will ignore them as though they were comments; if we run into any problems with the code later, we can erase the brackets and see the diagnostic printed to the screen as we play.
We could have done all that by hand, but the initialization requires a little less work.
And because even though the ticket machine is a container, we don't want to say (empty) after it in the room description:
After all that, we should probably give the player a chance to win, as well:
In fairness to the Metropolitan Transit Authority, we should admit that most of the ticketing machines in the real New York subway are better than this, and will accept, say, a debit card. But that would be so much less exciting to implement.
283. ★★★ Introduction to JugglingSuppose we have a whole catalog-full of equipment that the player might want to purchase and use. We'll start by defining our purchasing rules:
We allow things to have prices, and the player's price to indicate how much money the player has:
Because we're allowing the player to order things that he can't currently see, we need to borrow a special kind of grammar from the Understanding chapter. All our orderable items in this example are toys, so "any toy" means any object of the toy kind, whether or not it is in view at the moment:
We should also handle the situation where the player orders another of something he has already bought and which is right in front of him:
So much for the general rules for this scenario. Now we move on to particulars: the actual items the player is allowed to order. Each item will have a description, a price, and a difficulty representing how skilled the player must be in order to make use of that item.
Since we are going to use price and difficulty in the table that defines our juggling equipment, we need to mention these kinds of value before the line that says how toys are defined.
| toy | cost | restriction | description | difficulty | outcome |
| an economy bounce ball set | $10.00 | "comes in set of three" | "A fairly ordinary rubber ball, solid color." | moderate | "You create of the balls a cascade of moving color." |
| an acrylic contact ball | $14.00 | "should be bought with ball polish" | "A large clear ball, not for throwing but for using in various hand tricks." | hard | "You rotate the ball between your fingers and pass it over the backs of your hands." |
| a UV-reactive contact ball | $55.00 | "appears to glow in dark rooms" | "Similar to the ordinary acrylic contact ball, but UV-reactive." | hard | "The ball glows as it passes between your fingers and over the backs of your hands, rolls up to your wrist, snaps through the air-- all apparently of its own accord." |
| a ball polish set | $10.00 | "useful only with acrylic contact balls" | "Three bottles of polish and a rag for keeping acrylic contact balls scratch-free." | hard | "You juggle the polish bottles with difficulty, since they are full of sloshing liquid." |
| a teaching beanbag set | $8.00 | "set of three" | "Soft, easily-juggled bag." | easy | "You juggle the beanbags with basic competence." |
| a stage ball set | $13.50 | "comes in set of three" | "Not much different in appearance from the economy bounce ball, but larger so as to be visible from a stage." | moderate | "You create of the balls a cascade of moving color, visible from quite a distance." |
| a fireball set | $33.00 | "will not be sold to minors" | "A ball has wicking and a fuel-source inside so that it will burn while being juggled." | hard | "You juggle the fireballs rapidly, careful never to hold any of them a moment longer than necessary." |
Notice that we are allowed to define "description" and other already-known properties in the table as well.
And of course this will be no fun unless the player is allowed to use the equipment:
Most toys are single things, and no harder to create than any other small items, but games often require a multitude of tokens to be combined, and this can be logistically tricky.
The classic example is a pack of playing cards, where the player must individually control 52 items but without fussy commands or verbose text being printed back. Jokers Wild ★★ provides a simple "one card at a time" approach; Tilt ★★★ is more sophisticated, with 52 independently accessible cards; Tilt 2 ★★★ can further judge the value of a selection of cards – the ranking of a poker hand.
Drawing cards from a shuffled pack is only one source of randomness. Games of chance also involve items drawn from a bag: Wonka's Revenge ★ provides just such a lottery. More often, dice are thrown. A single die is easy enough:
Quick, but not very good. Most dice games involve rolling more than one die at a time, to get a more interesting distribution of outcomes: they may also involve special rules applying to doubles, for instance. See Do Pass Go ★.
Typography for on-screen notations for chess and card games.
Because we remember the states of the individual dice, not just a total, we can make use of the combination rolled.
Inform keeps track of the order in which things have been put into a container. If we want to change that order without the player's intervention, we can move the things ourselves.
Suppose we want a deck of cards which the player can shuffle and draw from. Our first (rather tedious) task is merely to set up the deck as a table:
| suit | value |
| diamonds | 1 |
| diamonds | 2 |
| diamonds | 3 |
| diamonds | 4 |
| diamonds | 5 |
| diamonds | 6 |
| diamonds | 7 |
| diamonds | 8 |
| diamonds | 9 |
| diamonds | 10 |
| diamonds | 11 |
| diamonds | 12 |
| diamonds | 13 |
| spades | 1 |
| spades | 2 |
| spades | 3 |
| spades | 4 |
| spades | 5 |
| spades | 6 |
| spades | 7 |
| spades | 8 |
| spades | 9 |
| spades | 10 |
| spades | 11 |
| spades | 12 |
| spades | 13 |
| hearts | 1 |
| hearts | 2 |
| hearts | 3 |
| hearts | 4 |
| hearts | 5 |
| hearts | 6 |
| hearts | 7 |
| hearts | 8 |
| hearts | 9 |
| hearts | 10 |
| hearts | 11 |
| hearts | 12 |
| hearts | 13 |
| clubs | 1 |
| clubs | 2 |
| clubs | 3 |
| clubs | 4 |
| clubs | 5 |
| clubs | 6 |
| clubs | 7 |
| clubs | 8 |
| clubs | 9 |
| clubs | 10 |
| clubs | 11 |
| clubs | 12 |
| clubs | 13 |
We're going to describe the higher numbers as face cards, so it helps to write a new "to say" phrase.
| value | term |
| 1 | "ace" |
| 2 | "deuce" |
| 3 | "three" |
| 4 | "four" |
| 5 | "five" |
| 6 | "six" |
| 7 | "seven" |
| 8 | "eight" |
| 9 | "nine" |
| 10 | "ten" |
| 11 | "jack" |
| 12 | "queen" |
| 13 | "king" |
Now we get the shuffling of the deck from "sort in random order", so:
This will continue to work properly even as the deck is partially depleted. Speaking of which, suppose we want the player to be able to toss the cards one-by-one into a hat. They are going to need to be removed from the deck, so:
If we wanted to simulate a slightly more stimulating game, we could instead have a second table to represent the player's hand of cards and record each card drawn. That would get long for the purposes of example, however, so instead we will just admit that the player's life is an empty husk of existence:
We've simulated a deck of cards before, but only as entries in a table. This time we're going to do it more completely, with card objects that can be drawn and discarded, and referred to by name. The tedious way to do this would be to make 52 objects by hand and laboriously write out their names and understand rules.
A more sensible way is to make 52 identical card objects, assign them ranks and suits, and allow Inform to generate and parse their names automatically.
So:
Now, we're going to describe the higher numbers as face cards, so it helps to write a new "to say" phrase, just as we did in Jokers Wild. (A subsequent version of this example shows how to print card values with red and black symbols representing the different suits; see "Tilt 3".)
| term | value | topic |
| "ace" | "1" | "ace/A/one" |
| "deuce" | "2" | "deuce/two" |
| "three" | "3" | "three" |
| "four" | "4" | "four" |
| "five" | "5" | "five" |
| "six" | "6" | "six" |
| "seven" | "7" | "seven" |
| "eight" | "8" | "eight" |
| "nine" | "9" | "nine" |
| "ten" | "10" | "ten" |
| "jack" | "11" | "jack/knave/J" |
| "queen" | "12" | "queen/Q" |
| "king" | "13" | "king/K" |
This is enough already to let inform understand things like "ten clubs", but we want to add a couple of refinements. For one thing, we'd like to accept "of" when it appears in phrases such as "ten of clubs" (but not generically otherwise); for another, we'd like the player to be able to use various names for ranks. To this end, we need to borrow from the Activities chapter and modify the player's command before attempting to understand it:
It may be a bit confusing that the Table of Value Names has both a topic column and a term column, to all appearances essentially identical. But items in the topic column can be matched against the player's input, whereas items in other kinds of text column can be printed out; the two kinds of text are not treated identically by Inform, so we need to have both. Notice that the topic column contains entries like "jack/knave," which will match either "jack" or "knave" in the player's input.
Now to set up the deck at the outset. With some intelligent looping, we avoid having to declare every combination of suit and number individually:
And now we need a simple setting and some actions to manipulate the deck with:
The above phrase rounds a number to the nearest five, because it seems unrealistic for the player to be able to count a large number of cards in the discard pile at a single glance.
This next bit is an optional borrowing from the Activities chapter: we want to prevent Inform printing things like "You can see a discard pile (closed) here.", since we don't want the player to think of the piles as containers, even though Inform thinks of them in those terms.
Finally, we want the player to use "draw" and "discard" to manipulate his hand of cards:
In our previous implementations of playing cards, we've gotten as far as creating decks of individual cards that the player can draw and discard. But in a poker game, one doesn't just have a collection of cards: one has a hand of a specific kind.
Here we take on the job of writing an inventory listing for a poker hand that will reflect the real value of what the player has drawn. To do this, we create a rulebook to sort and assess the cards in the player's hand; its possible return values are limited to the kinds of poker hands that exist, from "high card" to "royal flush".
The first three sections, creating the deck of cards and the means to parse their names, are identical to those we've already seen in Tilt 1; new material begins at section 4.
For the purposes of demonstration, we're simulating something akin to five-card draw without wilds; stud or hold-em variations would add some other complexities.
| term | value | topic |
| "ace" | "1" | "ace/A/one" |
| "deuce" | "2" | "deuce/two" |
| "three" | "3" | "three" |
| "four" | "4" | "four" |
| "five" | "5" | "five" |
| "six" | "6" | "six" |
| "seven" | "7" | "seven" |
| "eight" | "8" | "eight" |
| "nine" | "9" | "nine" |
| "ten" | "10" | "ten" |
| "jack" | "11" | "jack/knave/J" |
| "queen" | "12" | "queen/Q" |
| "king" | "13" | "king/K" |
New material begins here. We want to start by grouping cards together, but identifying poker hands only if the player holds a full five cards.
The ranking of poker hands traditionally depends on three features: 1) whether all the cards are of the same suit (flush); 2) whether the cards constitute a numerical run of ranks (straight); and 3) how many cards or sets of cards are of matching rank (pairs, three of a kind, and four of a kind). Here we will start by assessing our hand to determine these qualities:
For convenience in identifying hand features, and for elegance when we print the hand-listing, we start by sorting the cards in the player's hand so that the high-ranked cards are listed first. It is rare that we want to concern ourselves with this, but as we saw in the section on "Looking at containment by hand" in the chapter on Change, Inform keeps an ordered list of the items inside any given container; so it does order the objects in the player's hand, and the ordering depends on which things were added to the hand most recently. By moving something to the player's hand again (even if it was already there), we change this ordering, and wind up with a sorted hand.
This last printing instruction is there for diagnostic purposes: later we'll add a testing command to turn debugging on and off; when it's on, the game will print out its card list at various stages in sorting, to help us trouble-shoot any problems. In normal play, however, this will be off.
Next up, a check to see whether the player has a flush:
Now we check for straights; this is slightly complicated by the fact that an ace can be either the bottom of a low straight (lower than 2) or the top of a high straight (higher than king), so we explicitly check both possibilities.
And finally, we need to identify any groups of cards of the same rank. We want to know how many groups there are and how large each group is (though in practice there can only be one group of three or four in a standard-sized poker hand). We also want to mark any grouped cards so that we can move them to the front of the player's hand when we take inventory.
This definition is a convenience so that we don't have to write so many explicit loops in the following rule:
Next we tweak our sorting to reflect the make-up of the hand. There are two reasons why this might differ from the straight highest-to-lowest sort we did earlier:
1) we want to list aces as high unless they are serving as the bottom of a low straight, in which case they should appear last;
2) we want combinations to appear at the front of the list, sorted from highest value to lowest value: larger combinations first, then smaller combinations, and combinations of equal size sorted by rank.
Now, having determined the salient qualities of our hand, we run through rules in order from the highest kind of poker combination to the lowest. Because of the order of the source, Inform will choose whichever combination applies first.
And finally, we need to define our debugging variable here, even though we won't give the player the ability to turn it on and off except in the special testing section.
For many examples, a test-me script is enough to prove that the example does what it ought. This example, though, is a bit more complicated, and hard to test randomly. The remainder of the source here shows how we might write a test to verify the desired behavior of our rulebook. Those who are only interested in the rulebook itself can stop reading at this point.
For the sake of testing our rules, we provide an apparatus that will load the player's hand up with sample hands of each kind, then show the result to make sure that the hand is being correctly identified.
The somewhat rough-and-ready principle of this table is that we will overwrite the cards in the player's hand by resetting their ranks and suits; every five rows of the table represent a new poker hand for the game to attempt to sort and identify. These include one example of each of the major kinds of poker hand, plus a couple of variations involving aces which test the special sorting rules.
| set suit | set rank | |
| spades | 1 | [royal flush] |
| spades | 13 | |
| spades | 12 | |
| spades | 11 | |
| spades | 10 | |
| clubs | 12 | [straight flush] |
| clubs | 11 | |
| clubs | 10 | |
| clubs | 9 | |
| clubs | 8 | |
| diamonds | 8 | [four of a kind] |
| hearts | 8 | |
| spades | 8 | |
| clubs | 8 | |
| clubs | 3 | |
| clubs | 1 | [full house] |
| spades | 1 | |
| hearts | 10 | |
| spades | 10 | |
| clubs | 10 | |
| hearts | 2 | [flush] |
| hearts | 5 | |
| hearts | 7 | |
| hearts | 11 | |
| hearts | 12 | |
| hearts | 1 | [straight] |
| spades | 13 | |
| diamonds | 12 | |
| clubs | 11 | |
| hearts | 10 | |
| hearts | 2 | [three of a kind] |
| spades | 2 | |
| clubs | 2 | |
| clubs | 4 | |
| spades | 3 | |
| diamonds | 6 | [two pairs] |
| spades | 6 | |
| clubs | 7 | |
| diamonds | 7 | |
| hearts | 9 | |
| diamonds | 6 | [two pairs, ace high] |
| spades | 6 | |
| clubs | 1 | |
| diamonds | 7 | |
| hearts | 1 | |
| hearts | 12 | [pair] |
| spades | 12 | |
| diamonds | 10 | |
| spades | 7 | |
| clubs | 4 | |
| diamonds | 13 | [high] |
| hearts | 11 | |
| spades | 9 | |
| clubs | 7 | |
| diamonds | 5 | |
| hearts | 1 | [tricky sorting: low straight] |
| diamonds | 2 | |
| spades | 3 | |
| diamonds | 4 | |
| diamonds | 5 |
Many things can be read, from warning notices to encyclopaedias, and a range of techniques is needed to provide them because the quantity of text, and how it presents itself, can vary so much. With a small amount of very large type, the player should not need any command at all to read the text:
If the print is smaller, or the object portable, the player will expect to use the EXAMINE command:
But if the object is a leaflet, say, EXAMINE should only describe the cover: READ would be the command a player would expect to use to get at the text itself. Inform normally defines READ to be the same command as EXAMINE, which is good for things like the business card, but counter-productive here. The Trouble with Printing ★ shows how to separate these two commands, allowing any thing to have a property called its "printing" for text produced by READ, which will be different from its "description", the text produced by EXAMINE.
If the object is a lengthy diary, say, nobody would read it from cover to cover in a single IF turn. We might then want to allow the player to turn the pages one by one, with commands like READ PAGE 4 IN DIARY or READ THE NEXT PAGE: see Pages ★.
If the object is an encyclopaedic reference work, the player would consult named entries: see Costa Rican Ornithology ★★★, which allows commands like LOOK UP QUETZAL IN GUIDE.
Still larger sources of text often occur in IF: libraries or bookshelves, where many books are found together, and it is clumsy to write them as many individual items. One approach is to simulate an entire bookshelf with a single thing: see Bibliophilia ★★. (This is much like looking up topics in a single book, except that each topic is a book in itself.) Another is to provide each book as an individual item, but have them automatically join together into a single portable collection: see AARP-Gnosis ★★.
Signs, leaflets and encyclopaedias, being printed, have a wording which will never change during play. But sometimes the player reads something which acts of its own accord. Text substitutions are usually all that is needed to achieve this:
This is easy because we know all the variations we want. But what if we want the player to write his own text, for instance, adding to a diary? This is trickier, because it means storing text as the player typed it, and replaying it later. (And suppose the player types reams and reams of text, not just a few words as we might have hoped?) The Fourth Body ★ and The Fifth Body ★★ show how to use an external file – a multimedia trick requiring features only available if the project is set to the Glulx story file format – to handle even the most difficult cases.
Should we want a computer that responds to vocal commands, as in ASK COMPUTER ABOUT KLINGONS, the built-in extension Inanimate Listeners will allow the player to talk to inanimate objects as well as people.
Since we defined reading as an action requiring light, we could further distinguish reading and examining (if we wanted) by writing some different visibility rules for it.
303. ★ PagesSuppose we have a book that the player must consult page-by-page, and we want to be able to accept all of the following input:
One approach would be to write many different understand rules and actions: one action for reading randomly, one for reading a specific page, one for reading the first page, one for reading the previous page, one for reading the next page, and one for reading the last page. But this gets tedious to construct and maintain.
More usefully, we could consider that all of the last four options are essentially the same action at heart: the player is asking to read a page in the book using a name rather than a number, and we will have to perform a minor calculation to discover what the number should be. Here's an implementation using named values to resolve this problem:
| page | content |
| 2 | "dhuma jyotih salila marutam / samnipatah kva meghah / samdes arthah kva patukaranaih / pranibhih prapaniyah" |
| 13 | "amathesteron pws eipe kai saphesteron" |
| 50 | "Rrgshilz maplot..." |
Some mystery games supply the player with an in-game system for taking notes, in case he doesn't want to rely on scraps of paper next to the computer. One way of doing this is to write out all the player's notes and observations into a notebook file, whose contents can be retrieved during play (or, indeed, after it).
We'll first invent a general system for writing text into notebooks, by creating a new kind called jotter. Each individual jotter will have its own disc file, and there will be basically three things which can be done with jotters: erasing, reading and writing.
This is all as might be expected, except perhaps for the business of the "currently erased jotter". Why copy "pad" into this – why not simply write "[heading of the pad]"? The answer is that "pad" is a temporary "let" value, and cannot be used inside other phrases, such as the "write … to …" phrase.
We want to erase any jotters when play begins, as otherwise text left over from any previous games will still be visible:
Now we need to create rules to allow the player to control reading, writing and erasing. Reading we will handle with the ordinary examining action, but we create new actions for writing and erasing. A nice little trick allows WRITE WHATEVER to default to writing WHATEVER in a notebook being carried.
That completes a general-purpose implementation of jotters, and we put it to use:
Suppose we want a bookshelf with a very large number of books on it. They aren't to be taken or carried around in the game, but they should be mentioned, and the player should be allowed to look them up by name. Furthermore, the player's attempts to examine something unrecognized should be understood as an attempt to look up a title -- but only when the player is in the presence of the books. The rest of the time such requests should be rejected in the usual way.
| topic | title | description |
| "Reading Greek Death" or "reading/greek/death" or "greek death" | "Reading Greek Death" | "A dense orange paperback treatise on the development of Greek eschatology." |
| "TAPA/Transactions/134-2" | "TAPA 134-2" | "Transactions of the American Philological Association from 2004." |
| "Oxford Classical Dictionary" or "OCD/dictionary/classical/oxford" | "Oxford Classical Dictionary" | "A hefty reference with short articles on everything from Greek meter to ancient cosmetics." |
| "Collected Dialogues of Plato" or "Plato/dialogues/hamilton/cairns" | "Collected Dialogues of Plato" | "All the Platonic dialogues -- some, admittedly, in rather tired translations -- but still a useful single volume, ed. Edith Hamilton and Huntington Cairns." |
| "Adobe Illustrator CS User Guide" or "user guide" or "adobe illustrator" or "adobe/illustrator/cs/user/guide" | "Adobe Illustrator CS User Guide" | "Hello, how did this get here? A suspiciously familiar name is scribbled inside the front cover..." |
Now if we type >X HERCULES in the Lounge, we will get
thanks to our somewhat slovenly implementation of the Lounge scenery; but in the Reading Room,
In practice we might also want to extend our coverage somewhat to handle a case where the player tried to take books from the bookshelf: currently that would not be understood.
335. ★★ AARP-GnosisSuppose we have a complete Encyclopedia in our game. The player is allowed to pick up the whole set (there must not be too many volumes), but also to do things with individual volumes, and indeed to scatter these volumes all over the place. Putting a volume back in the same place as the rest of the Encyclopedia should, however, restore it to the collective. We will start out by defining general rules for collectives like this:
Now the real work begins. One reason to make this an activity is that we might easily want to override it for specific objects; for instance, the generic collecting activity here would not deal properly with collectives of clothing where some items might be worn and others not. In that case, we would want to write another, more specific "collecting" activity to handle the complexities of fashion.
And now for a cheerful scenario:
Let's have the Encyclopedia describe itself differently depending on whether it's all in one place:
The implementation here is much like that of the previous example, except that we allow the player to write his notebook input as a separate command, leading to an exchange such as
The opening is much as before:
Now what happens is that the player, having typed WRITE IN NOTEBOOK, will be faced with a ">>" prompt instead of the usual ">": a sign that the input mode has changed.
The next code is to react to reading a command. Whatever the player types at the >> prompt when the target jotter is set will now be recorded in the notebook, though with a character limit of about 60-100 characters depending on how much upper-case and punctuation he uses. (There are ways to lift the character length restriction as well, but they would take us into deeper waters.)
The following relies on quite a number of features we haven't met yet: tables, rules for printing names, instructions for understanding the player's commands. It is offered simply as an example of how a fully implemented book might be handled in Inform.
With this "topic understood" phrase, we're telling Inform to print back the word or phrase that the player was attempting to look up. This overrides the more general default response, "You discover nothing of interest in the book."
We now have the essential elements to construct whatever books we like. Now let's have an example of a specific book:
We will come back to the idea of tables and table names later, but for now the important thing is that we have instructed Inform to look up its answers to consulting the bird guide in this form:
| topic | reply |
| "[red]" or "[red] bird/macaw" | "You flip through the Guide for a while and eventually discover a reference to the [scarlet macaw], which appears to correspond with what you see before you." |
| "quetzal/trogon" or "resplendent trogon" | "The entry on the quetzal is quite lyrical, describing its brilliant plumage, flashing and igniting in the sunshine, which is supposedly sufficient to lure birdwatchers from all over the world. Unfortunately, the quetzal is described as being bright emerald in color, with a pink fuzz on its head and a long soft tail 'like a feather boa'. None of these describes your visitor." |
The topic column is a bit special: it matches the player's input, and is not meant to be printed out again. Topic columns will be discussed further in the chapter on Tables. (Note also that, however it may appear in the documentation, the topic column should not be spanning multiple lines in our source text.)
We may also compress long or complicated topics by creating bracketed abbreviations, and in fact it's useful to do so now, to explain the red token we just used:
This technique is discussed further in the chapter on Understanding.
If we wanted more books, we could define those in the same way, giving each its own separate contents table to be used for consultation. But for the sake of the example we will keep it simple, and move on to the scenario itself:
Writing on something is only one way a player can change its visual appearance. IF authors have long been wary of paint brushes, because a sufficiently motivated player could go through a whole landscape like a graffiti artist with a railway bridge. We want to give the player the illusion of freedom of action, while avoiding a situation where unlimited numbers of different decorations might be needed – that would need a table of potentially unlimited size.
One approach is to limit the number of items which can be decorated. In Palette ★, only the canvas can be painted, and each image overlays the last. Early Childhood ★★★ increases the range to allow a whole kind ("block") to be painted, and also shows how the changing colours can be used to distinguish between otherwise identical objects.
Brown ★★★ finds a different way to limit the number of simultaneous decorations: almost anything can have a red sticky label attached, but there is only one red sticky label. (So to decorate a new item, the player must first un-decorate an old one.)
Electricity and Magnetism for another form of stickiness.
There are hundreds of traditional pigments, from lampblack to burnt sienna, so we will confine ourselves to just two:
Here is the essential point: whenever we ATTACH LABEL TO something, it becomes part of that object.
And of course the label cannot be stuck to itself or to more than one thing at a time.
Much of the rest is just tidying to make sure that the player's commands are redirected into the right syntax.
We could have created a new "sticking" action, but to keep the example short we will use the built-in "tying" action instead, and respond to the command "stick" just as if it were "tie".
This would be a one-star example if it were not for the repainting:
But a kind cannot change during play, so this will not do. Instead, the colour will have to be a property of the block. So we might first try this:
Which is fine, so far as it goes, but the colour property is not at all visible to the player, who simply sees "eleven blocks". We thought of colour as being something outwardly apparent, but Inform does not know this. To achieve a better effect, we will need features from distant chapters. The first is an activity called "printing the name of":
This too, however, is unsatisfactory. The individual blocks are correctly described, but we are unable to distinguish them during play: we cannot type "take a green block", for instance. And because the blocks are indistinguishable in play, they are still massed together as "eleven blocks" in room descriptions. We need to go one step further:
And now everything works nicely: the blocks are grouped by colour, and can be referred to by colour, and we can even change the colour of an individual block during play, using a bit of extra trickery from later:
The "device" kind provides for the simplest form of machine: one which is, at any given moment, switched on or switched off. Inform looks after this state, but leaves it to us to make the machine actually do something:
One primary dictionary definition for a machine is "an apparatus using or applying mechanical power and having several parts", and we often use the "part of" relationship to build machinery. Control Center ★ provides a neat way to display the component parts of a machine to the player who examines it.
One component almost always part of an electrical machine is the (literal) switch, lever or button to control whether it is switched on or off. In Model Shop ★★ just such an on/off button is automatically made part of every device.
While an electrical device has only two states, a mechanical machine might have many, and for these the best approach is to define a kind of value naming the possibilities: see Signs and Portents ★★★, where the states are the possible destinations pointed towards.
Perhaps stretching the definition of "machine", What Makes You Tick ★ demonstrates a fishing pole which the player can put together from several pieces.
Bags, Bottles, Boxes and Safes for a safe that can be dialed to different combinations.
It is straightforward to make a rule that anything with parts must mention all those parts during an EXAMINE command:
Now whenever we look at any object with components, we will first see the description, then a list of parts which belong to it. The following refinement brings in elements of later chapters, but it may be worth noting: because we've written our rule as an "After examining…", anything that pre-empts the operation of the examine command will also prevent that rule from occurring. So for instance:
…would not result in the needle being mentioned.
Suppose we want to let the player build a fishing pole out of three parts: a hook, a string, and a stick.
There are several things we must account for here. One is that our combination verb should be insensitive to ordering: it shouldn't matter whether the player types COMBINE STICK WITH STRING or COMBINE STRING WITH STICK.
Second, we need to make sure that our implementation handles intervening stages of assembly gracefully. The player should be able to combine string and hook first, or string and stick first, and be able to complete the assembly in either case.
Our implementation here uses a table of lists to determine which combinations of inputs should produce which result object. Because we sort our lists before comparing them, we guarantee that the player's ordering doesn't matter: COMBINE STICK WITH STRING will have the same effect as COMBINE STRING WITH STICK.
What's more, our implementation could be expanded to account for many other assemblages, if we wanted object-building to be a running theme of puzzles in our game.
| component list | result |
| {stick, string} | hookless fishing pole |
| {wire hook, string} | hooked line |
| {hooked line, stick} | complete fishing pole |
| {hookless fishing pole, wire hook} | complete fishing pole |
This kind of implementation makes sense if we don't intend the player to take the fishing pole apart again, or to refer to any of its component parts once it is built. For an alternate approach that does allow assembled objects to be taken apart again, see "Some Assembly Required".
57. ★★ Model ShopSuppose we're particularly mechanically-minded and would like a game in which all of our mechanical devices have buttons to turn them on and off.
Here we are making a rule about how our hypothetical buttons will interact with the machines to which they belong. Instead of pushing… is a rule that pertains to actions, and we will learn more about these in the chapter on actions. "…which is part of a switched off device" provides a specific circumstance – this is only to apply to buttons that are stuck to a machines that can be turned on or off. "(called the machine)" tells Inform that if it finds such a device, it should thereafter refer to it as "the machine." (The called syntax is explained further in the chapter on Change.)
A set of three more rules will complete our instructions about using buttons to control devices:
Then we hand out buttons with a free hand:
And now the game will have a model train's button and a toy elephant's button.
It may be that we want (as an added nuance) to add other names for these items. While we would want an assembly to create objects such as "Lucy's hand" and not "Lucy hand", it is entirely reasonable to want to talk about the model train button or the elephant button. We could define these additional names like so:
In the second case, we are defining [train] to mean any of the three phrases "train", "model", and "model train"; so "[train] button" will match "model train button" or "train button" or "model button" equally well. See the chapter on Understanding for more on how to create alternative phrasings for the player to use.
53. ★★★ Signs and PortentsIn order to interact with the signpost, we will need to make use of some action rules:
IF authors often provide clues or background information to the player by means of radio broadcasts, TV shows or video tapes because they can talk to the player without needing to listen back, or to react to what the player does. The simplest radio set, like the one in Aftershock ★★★, really only has one thing to say: which is serendipitously being broadcast just at the moment the player tunes in (regardless of when that is). The next simplest approach is to spool a broadcast on an endless loop taking several turns to play through, as in Radio Daze ★.
Televisions come in all shapes and sizes, and Aspect ★ allows their shape ("aspect ratio") to be described by the player.
In Channel ★★, we can also refer to the television by what it is currently showing: thus WATCH CHANNEL 4 will work if the set is indeed tuned to 4. In Channel 2 ★★★, numbered channel changing is taken further: we can now TUNE TV TO CHANNEL 3, as well. Channel 2 ★★★ is a reasonable base implementation of a television for many purposes.
Named properties are not the only kind that Inform is able to understand referring to an object. We can also use unit and number properties to distinguish things from one another, as here, where televisions have aspect ratios:
We might want to allow every television to be tuned to a channel (a number property) which the player could refer to, so that
would be directed to the appropriate television object, if any television is turned on and tuned to the correct station. We might now write:
| current channel | output |
| 0 | "The screen of [the noun] is completely black." |
| 4 | "A gloomy female news anchor describes the latest car bomb in Baghdad: 104 dead today, and no sign of change." |
| 5 | "A couple of contestants in spangled scarlet outfits are performing an energetic paso doble." |
| 13 | "On-screen, Ichiro is up to bat with one man on second and no outs." |
Our previous implementation of televisions ("Channel 1") doesn't allow the player to type things like
nor does it deal with player input like
or
where no television is specified. When we are designing commands which involve two elements (here, a television and a channel number), it's usually a good idea to allow the player to specify those elements in either order, as we saw demonstrated briefly in "New commands for old grammar".
We might, therefore, want to add a few refinements: first by defining a "[channel]" token that will accept input of the forms "[number]" and "channel [number]", and second by creating some additional "Understand" lines that will accept variant versions of the player's input.
| current channel | output |
| 0 | "The screen of [the noun] is completely black." |
And we add the scenario-specific content to our Table of Television Channels; in the case of channel 13, we provide for a changing sequence of events using text variations.
| current channel | output |
| 4 | "A gloomy female news anchor describes the latest car bomb in Baghdad: 104 dead today, and no sign of change." |
| 5 | "A couple of contestants in spangled scarlet outfits are performing an energetic paso doble." |
| 13 | "[one of]On-screen, Ichiro is up to bat with one man on second and no outs.[or]Ichiro has singled to first and the other man is on third.[or]The next batter is in the middle of flying out.[or]Everything looks rosy until the men in black pull off a double-play and retire the side.[or]The channel has cut to a commercial.[stopping]" |
The built-in behavior of Inform is to print a line after a device is examined, saying whether the item is on or off. This is often inappropriate, and we could simply turn off that behavior in general by instructing Inform to ignore the "examine described devices rule" (see the chapter on rulebooks).
Perhaps, though, we would like continue to have a short passage about the action of any switched on device; we'd just like a little more control over what it says from time to time. And in that case, we might change the rule to give a new activity control over that portion of the description:
Borrowing from the rulebooks chapter, we can replace the standard "examine described devices" rule with something that uses this activity.
Thus far we have essentially replicated the original behavior, but we've made it possible to write specialized behavior for devices, and to invoke that behavior in other places:
This might be useful for an electric lamp kind:
And with our activity, we can override the flashlight's electric lamp behavior with new behavior:
…or give special actions for the radio:
Telephones are much harder to achieve than televisions and in some ways as difficult to make convincing as a human character is – though of course there are corners which can be cut: we could have the reception drop off, or the other party hang up in a misunderstanding, and so on.
A single telephone line is tricky enough to provide that one might just as well have a general solution providing a whole network. Four Cheeses ★★★ demonstrates a system where we can dial either people or numbers: CALL JANET ON TELEPHONE, or CALL 7103, for instance.
While Four Cheeses ★★★ provides only four-digit phone numbers, like internal company extensions, Alias ★★★ shows how to manage US-style seven digit numbers.
Finally, we might occasionally want the player to be able to address a microphone or telephone receiver directly when the identity of the person on the other end is unknown, in the form TELL MICROPHONE ABOUT CRIME. Ordinarily Inform will disallow this because we're not allowed to talk to inanimate objects, but the extension Inanimate Listeners provides more options.
Saying Complicated Things for more approaches to conversation.
Because we've said that connection is a reciprocal, one-to-one relationship, Inform will do the rest of the bookkeeping: if (for instance) we telephone someone else, the first connection will be broken automatically.
To avoid annoyance, we should also let the player use CALL #### as well as CALL #### ON TELEPHONE. A rule from the chapter on Activities comes in handy here:
Things might be a little more complicated if we had cell phones that could be moved around, but for right now the player can only touch a maximum of one phone at a time.
Suppose we further want to allow the player to call people up by name, but only if they've already been encountered or are familiar to the player for some reason.
And finally we want to make sure that calling random other numbers produces a sensible result:
A note about this scope addition: the player can refer to the other party whenever he has the other person on the phone. He can't, however, see or refer to anything that person might be holding or wearing, thanks to the "but not its contents" option.
Furthermore, the player can't actually do anything to that person that requires touching. That's because of the reaching inside rules, which govern whether the player can reach through intervening barriers such as rooms. (See the Advanced Actions chapter for more about changing reachability.) There are two things we might want to be careful about, though.
First, we should specifically disallow the player from looking at the person on the other end of the line. Since sight doesn't require touching, the reaching inside rules will not be consulted about a command such as EXAMINE BOSS or LOOK UNDER BOSS. We can, however, intervene in such cases using the visibility rules, which are consulted for any actions that "require light" (including EXAMINE and LOOK UNDER). Here again we borrow some options from the Advanced Actions chapter:
Second, though the existing reaching inside rules are adequate to stop us from touching the person on the other end of the line, the response that's currently printed is a bit generic: it just says "You can't reach into [the room containing the person]." Let's add our own custom reply, instead:
This portion supplies a simple method of conversation; but we could substitute some completely different conversation system if appropriate. The effect of the telephones is that we are allowed to talk to characters in distant locations under certain circumstances, after which the usual conversation rules apply.
In a game where the player could walk around, we would of course want to add a before rule so that he automatically hung up any phone he was using before leaving the room.
| topic | reply |
| "love/passion/tonight/night" or "night of passion" | "'...Sorry, what?' she asks. 'I wasn't listening.' Oh. Maybe she'd go for some pizza, though." |
| "pizza" | "'I'd love some. No pepperoni, though,' she says, sounding dreamy. Yes, this is definitely time for a call to your old friend, the pizza boy." |
| "imminent ninja attack" | "'Don't worry about it,' says the boss crisply. 'I have everything under control.'" |
| topic | reply |
| "pizza" | "'Pepperoni special tonight!' he says proudly." |
| "pepperoni" | "'Pepperoni is included free on ALL our pizzas,' he says proudly." |
| "no pepperoni" | "'Well, I don't see why you'd want that,' replies the boy sniffily. 'It's free!'" |
| "jalapeno" | "'Sorry, we're out of jalapenos this evening. There was a run on them.'" |
| "sausage" | "'Sausage, sure, we can do you sausage.'" |
| "canadian bacon" | "'There's currently an embargo on Canadian pig products.'" |
| "cheese" | "'We use four kinds,' says the boy, then lowers his voice confidentially. 'Actually, two of them are the same. Nobody ever counts. The stringy one, the one that comes in dollops and the orangey one. You know.'" |
| "pineapple" | "'We could put pineapple on there, sure,' says the delivery boy, in a tone that lets you know his opinion of people who order fruit-based pizzas." |
| "pineapple and garlic" | "'What kind of crazy combination is that?' demands the delivery boy, finally losing all self-control." |
| "delivery" | "'Well, I don't know,' says the boy in a worried voice. 'Last time I came there were attack dogs. And ninjas.'" |
| "massive gratuity" | "'There's no use in a big tip you don't live to spend,' says the delivery boy quite firmly." |
| topic | reply |
| "imminent attack" | "'Yes, still on for tonight,' confirms the voice at the other end of the line." |
| "pizza delivery boy" | "The voice, in tones of velvet, indicates that it cannot guarantee the safety of any delivery persons whomsoever." |
…and it more or less writes itself from there.
253. ★★★ AliasSeven-digit telephone numbers are too long for Inform to handle when compiling to the Z-Machine, but they will work under Glulx. To have this example succeed, make sure that you have selected the Glulx option in your settings menu.
Now we borrow some techniques from the Understanding chapter to set up dialing actions:
This much is enough to let us dial telephone numbers and have Inform report that we've done so; it doesn't actually provide a telephone system such that we could reach and converse with other characters (but see the other telephone examples in the recipe book for more on how one might do that).
We'll set up a little political espionage scenario from which our player can make calls:
Borrowing again from the chapter on Understanding, we might arrange things so that the player knows and can call a few standard numbers with such syntax as CALL HOME:
And what if we'd like to have the player learn some phone numbers during the game?
This will understand CALL STEPHEN once the paper is examined; before that, the player will just get the "That's not a number you know" response that Inform uses for all attempts to call unknown names.
We'd better plant this paper for the player to find:
The simplest form of clock is a wrist watch. Here is a choice of analogue or digital:
Better clocks would allow us also to set the time, and to stop and start them: see Tom's Midnight Garden ★.
Scientific instruments provide sharper versions of our own senses. In the case of vision, they allow us to see closer up, or further away. It's a convention of IF that people can normally see only the current location, that is, they cannot see from one location into another. The boundary of the current room is like a horizon, even out of doors (though it's true that there are ways to disguise that with a continuous outdoor landscape). Ginger Beer ★★ provides a telescope able to see into other rooms.
Witnessed 2 ★ provides a meter which measures how close a ghost is to the player.
Continuous Spaces and The Outdoors for more on seeing into adjacent locations.
Heat for infrared goggles.
Time can also be understood as a token, and the time parsed will be recorded as "the time understood". So therefore, if we wish for clocks which may be set:
Suppose we want to have a pair of linked lenses so that the player can look into one of them and see things which occur in room containing the other lense.
We begin simply with a bit of environment for the player to wander around:
Now for the lenses themselves:
Here is the critical bit, which needs to be somewhat flexible, since the large end of the telescope could in theory be left anywhere in the game (and should still work).
We also want to make sure that the player who looks through the small lense does not see the large lense listed among the contents of the other location:
And we're done.
Recording what is going on, for later playing back or examination, is difficult because the range of situations is very complex. Exactly how much information should we store when we make a recording, and will this require problematically large tables? Will it be difficult even to do at all?
The usual approach is to record only basic details of events or situations. In If It Hadn't Been For… ★ the tape recorder preserves only a few different sounds – footsteps, creaking, rustling – rather than capturing exactly the sound of every action taking place in earshot. In Claims Adjustment ★★, we can take up to 36 Polaroid-style photographs, but each is described only by saying what it is a photo of. Thus we can have a photograph of a vase, or even a photograph of a photograph of a vase (because that too is a thing), but not a photograph of a still life in which several items have been gathered together by the player. That would ordinarily require too much storage.
A similar trick, though involving impromptu sculpture rather than photography, can be found in Originals ★. (The artist magically "manifests" these models rather than sculpting the conventional way in order to avoid the nuisance of carrying around raw materials – wax maquettes and so forth – which would clutter up the example.)
Text, of course, can store arbitrary descriptions. Mirror, Mirror ★ provides a perfect visual recorder: it remembers a room description exactly as the player saw it at the time.
Actor's Studio ★★ provides a video camera that records and time stamps all actions performed in its presence while it is set to record.
Telephones for ways to speak to inanimate objects, which might be appropriate when, say, tape-recording a confession.
We start out by giving ourselves a capacious recording device:
| time stamp | sound |
| a time | some text |
And most of what follows is attaching sounds to various events. (We could have made noises associated with all the actions, but for simplicity we stuck to a few.)
The thing to note here is that the recording happens as part of Carry out, not as part of Report, so sounds will be recorded even when they are the result of non-player action when the player is not even in the room.
Now we're at liberty to record evidence of the ghost getting out of the cupboard and getting back in, while we ourselves stand about on the lawn.
369. ★ OriginalsWe rely here on the understanding-by-relations rules we've already learned, but there is an additional trick: we want to make sure that if the player types "original" or "actual", this word will not be taken to refer to the thing modeled:
Now our duplication command -- for the sake of simplicity, we'll suppose that in this scenario the player is duplicating objects by magic rather than creating them out of physical materials or supplies:
Now, the challenge is that we want to print the word "actual" before printing the name of an object, but only during disambiguation questions and only when we are not printing the name of the object as part of a model-name! (If we are not careful about the latter point, we will get responses such as "Which do you mean, the model actual deer or the actual deer?" which of course defeats the whole purpose.
The way around this is to remember that activities stack: we're printing the name of the deer while printing the name of a model that involves the deer. So if we set a flag while printing the name of a model, we can control the way the deer's name prints during the transaction. (We could use our …while clause to specify while not printing the name of a model, except that we're already using it for "while asking which do you mean", and these do not stack.) So:
Here we construct a video camera to track and play back actions:
| recorded action | time stamp |
| waiting | 9:00 AM |
Notice that both Lucas' implied taking action (picking up the croissant) and his eating action are recorded on the same move.
322. ★★ Claims AdjustmentWe start by creating a camera and a photograph object. As usual when we want to have a kind of object that can be dispensed in bulk, we start off with a bunch of identical instances of the object out of play (in this case, kept in an out-of-play container called "film roll"); we can then move them into play and give them characteristics when they're needed.
Each photograph can depict exactly one thing -- we're assuming that the player is not a landscape photographer here -- so we create a relation to indicate what is shown by each photograph. We'll then use that relation to determine how photographs are described, named, and parsed:
This allows the player to refer to any photograph by its subject: useful if we have a large number of them.
Now we create an action to let the player use the camera and generate these photograph objects:
Now we use two activities from the Activities chapter to describe the photographs to the player more elegantly:
And finally we provide a brief scenario to give the player something to take pictures of:
Inform normally assumes that everything is solid. It has no built-in support for gases or liquids, because they have so many different behaviours. For instance, is the important thing about gas that it diffuses, or that we breathe it, or that it mixes with other gases to react, or that it sometimes obscures vision? The answer depends on what we are trying to write, and for this reason Inform leaves it up to us.
Gases are easier to deal with than liquids, because they tend to be everywhere in their location at once (unlike a liquid which might form a pool on the floor) and because they diffuse and mix by themselves (rather than being carried around or brought into contact with each other by the player). On the other hand, unlike liquids, gases are compressible: they can be present at low or high pressures, that is, in low or high concentrations.
The simplest approach is the one in Only You… ★★★, where rooms are either filled with smoke or else smoke-free. Smoke gradually fills through the map, obscuring vision: no attempt is made to conserve the total quantity of smoke, as we assume that some fire is churning it out continuously to replace what diffuses away.
Lethal Concentration ★★ and Lethal Concentration 2 ★★★ simulate a gas diffusing through a three-dimensional maze of rooms, and becoming dangerous above certain concentrations. There is just one possible gas, and it is modelled by giving each room a number which represents the concentration (in parts per million). This enables us to conserve the total amount of gas, or to have it released or captured by sources and sinks of given capacity.
This could be extended by giving each room similar concentration levels for other gases, and providing for the diffusion rule to notice when different gases come into contact; or by giving a concentration (and also, for realism, a volume) to each closed container, applying rules for capturing and releasing gases as containers are opened and closed.
A technical note: it would be possible to write "repeat with space running through rooms… repeat with second space running through rooms adjacent to the space" instead, but in practice this loops through all the rooms * all the rooms again * all the directions (to determine adjacency). Phrasing the loop this way omits the second multiplier. For a map of 25 rooms, this means that the loop runs 25 times faster than it would otherwise, and of course for a larger map the effect would be even more dramatic.
And, for testing purposes, a square grid of rooms:
For variety of testing, here is another room set-up, this time with some corridors and walls within; uncommenting it, and commenting out the connected grid, will let us explore what would happen in alternative cases, to prove to ourselves that the model works consistently.
For the sake at least of seeing what's going on in the example, let's also provide the player with the means to view the gas diffusion graphically:
The values set for these would depend on the type of poisonous gas in question; we'd want to adjust appropriately.
Now, in theory we might also want to account for sources and sinks, items that either inject poisonous gas into the environment or remove it again. For simplicity, we will assume that these contributions can also be calculated in ppm and that the total number of inert and poisonous gas molecules in a room never changes (so if poison gas molecules are added, an equal number of inert molecules are removed). If room pressure were able to change, our model would have to be improved, so let us assume for now that that never happens. We want this sink/source business to calculate before any other portion of the diffusion rulebook, so set it as a first diffusion rule.
Suppose we want to have smoke that spreads from room to room, gradually filling the entire map with a clogging smoke. Having it spread every single turn would make for a pretty rapid diffusion, so we temper this by having it spread only on even-numbered turns, instead. Conveniently, Inform by default already knows about even and odd numbers, so we can write:
This is a slight variation on the previous gas diffusion example: the main difference is that gas preferentially moves towards lower rooms, and will gradually settle in the bottom floor. We do this by calculating the probability of movement separately for each pair of rooms.
If we wanted, we could introduce other concerns into the calculation here: open and closed doors, windows between rooms, rooms that are outdoors vs. those that are indoors, and so on. The possibilities are numerous, so we will stick with the simple principle that our poison gas sinks.
And just for fun, this time we'll make the grid prettier, too; but this will work only on the Z-machine setting, not Glulx.
Liquids are notoriously difficult to simulate well. A fully thorough approach consumes endless storage and can be very finicky to write and keep realistic. It is essential to decide what aspect of a liquid's behaviour is actually needed in a given story, and to simulate only that. For instance, if we only need a little chemistry, where a player can add (say) water to salt and make a solution, we do not want to fool around with calculating quantities or concentrations: what's important is that "some water" (amount unspecified) combines with "some salt" to produce "some salty water". We should no more calculate precisely here than we would work out where all the furniture is to the nearest inch. Good advice for handling liquids is to simulate the least amount of realism possible, but no less.
Sometimes all we want is a down-in-one drink: we needn't simulate the actual liquid, just the bottle it comes in, and all we need is to handle the "drinking" action. See Beverage Service ★, and also 3 AM ★★★, where carbonated drinks can be shaken – again simulating the vessel, not the liquid.
Some elementary biochemistry in Xylan ★★ is done simply by… well, the point is that two different liquids are represented by single things each, and a chemical reaction simply switches one for the other.
In Frizz ★★★, we allow any container to be filled with water (only) and we simulate what happens to any solid objects also inside: some waterproof, some not. Flotation ★ provides a well (always full of water), with rules to determine whether things dropped into it should sink or float.
Next we move up to quantitative approaches, where we remember not just whether a liquid is present, but how much of it. In its simplest form, we could have a drinking vessel from which we draw in sips, so that it can be full, half-empty or empty: see Thirst ★.
The example with the best compromise between simulation quality and complexity is Lemonade ★★★. Here we provide a kind of container called a "fluid container", not just a single cup, and each such vessel has a given "fluid capacity". Each holds only a single liquid at a time (so no mixtures) and can be empty or full to any level (rounded off to the nearest 0.1 fl oz). We can fill one vessel from another (unless it would make a mixture). But liquids leaving these vessels must be consumed – drunk or poured away without trace: we cannot make pools on the floor, or carry liquids in our cupped hands. There is no object representing "lemonade": there are only fluid containers, but which can be called LEMONADE if that is what they now contain.
Savannah ★★★ is a light elaboration of Lemonade, showing how liquids might be poured on other objects, as for instance to extinguish a fire.
Noisy Cricket ★★★ extends Lemonade ★★★ to allow for mixing, though then the number of different possible mixtures is so large that complexity increases greatly. Lakeside Living ★★★ extends Lemonade ★★★ differently to add a "liquid source" kind, a form of fluid container which has infinite fluid capacity and is scenery – ideal for a lake, river or spring.
Bags, Bottles, Boxes and Safes for stoppered bottles which could also be used for carrying liquids around in.
Heat for keeping liquids warm in insulated containers.
Some kinds of game objects -- food, for instance -- can only sensibly be used once, and should then be destroyed. The EAT command already implements this, but suppose we also had a category of drinkable potions:
Here we want a rulebook to determine whether objects float or sink, so we create an object-based rulebook for the purpose. The more specific rules here, pertaining to corks and to inflated things, will be consulted first; then, as a default, the general flotation rule.
We also want a switch that can turn flotation off at will. The rule about the big switch will be observed before the others because the when… clause makes it more specific than the other rules in the flotation rulebook.
If we wanted, we could also put these rules into a rulebook in an explicit order, overriding Inform's automatic sorting by specificity.
And finally a few description rules to make things look prettier:
As we recall from the chapter on activities, "writing a paragraph about…" is an activity; activities are themselves structured as sets of object-based rulebooks. The activity "writing a paragraph about" uses three object-based rulebooks (before writing…, for writing…, after writing…). We could have made a flotation activity as well, but in general it is overkill to make an activity to make success/failure decisions. For that purpose an object-based rulebook is sufficient.
If we wanted to define a brand new verb that did affect a specific object, we might begin like this:
Of course, how our players will ever solve this problem is another question (especially if their biology and chemistry are both rusty). When adding entirely new commands to a game, it is often a good idea to provide as many ways of phrasing the command as possible; to drop hints about the correct phrasing within the game's text; or even to tell the player about the expanded command list in some documentation or help at the beginning of the game. So for instance we might also add
And these lines will also provide syntax for our new command, without interfering with the previous syntax. It's also good to anticipate alternative (British or American) spellings. People's typing habits are hard to overcome, even if they know you are spelling the word the other way. It is probably best not to annoy them unduly. So:
Then some text in-game might offer a clue, subtle or (since this is an example) blunt:
And finally, we could try adding instructions explicitly:
…though of course in fact these other commands won't be available until we define them, too.
This last approach, defining all the extra commands up front, is especially useful if these commands are very technical or unusual; if they are needed early in the game, before you've a chance to educate the player; or if they are not suggested by any in-game objects. A player who encounters a tool with an obvious use, such as a hairbrush, will likely think of trying to BRUSH things with it. It's harder to rely on his guessing actions that are both outside the range of usual commands and unrelated to any of the visible props, however.
192. ★★★ FrizzSuppose we have some items that get wet in contact with other damp things; in particular, if we touch anything wet while wearing a pair of gloves, the gloves too get damp. This requires that we be systematic about detecting all cases where contact occurs. So:
Now: whenever the player definitely touches something, we want to follow certain rules about the transfer of liquid. These rules need to come after an action's check rules (to make sure the action really occurs) and before the carry out rules (so that nothing has moved or changed yet). So we'll borrow from the chapter on rulebooks to create a whole new stage to the action, occurring between the check and the carry out phases:
Because the can of root beer should have some reactions to having been shaken later in the game, we need to borrow a few ideas from the chapter on Time:
Liquids, and all substances that can be mixed or broken off in partial amounts, pose a challenge to model in interactive fiction. The following example is a simple one, but adequate for many scenarios.
We start by assuming that all liquids in the game will always appear in containers. The player can pour liquids from one container to another, and the containers keep track of how full they are and describe themselves appropriately. The player can also refer to containers by content.
Mixture, however, is not allowed, nor is it possible to put liquids on other objects, pour them out on the ground, etc. These ideas would require a more complicated set-up.
We have allowed all liquids to be drunk, but it would be possible also to add checking, if we had a game where some liquids were beverages and others were, say, motor oil.
This is probably a drier description than we would actually want in our story, but it does allow us to see that the mechanics of the system are working, so we'll stick with this for the example.
Now we need a trick from a later chapter, which allows something to be described in terms of a property it has. This way, the story will understand not only "pitcher" and "glass" but also "pitcher of lemonade" and "glass of milk" -- and, indeed, "glass of lemonade", if we empty the glass and refill it with another substance:
And now the scenario itself:
Here we build very slightly on the existing liquid implementation to add a puzzle where the player puts out a fire with a bucket of water. Most of the liquid implementation remains the same as before, but now we understand the names of containers according to the liquids they contain.
The new material, pertaining to extinguishing fires, is at the bottom in section 2.
We will skip implementing the Pacific ocean itself, though the example Lakeside Living shows how to incorporate large bodies of water into our liquid simulation.
This is still a specific implementation: if we wanted to weave liquids together with a full-scale burning model (as in "In Fire or in Flood"), where pretty much any object in the game can be flaming (currently on fire) or damp (extinguished), we might generalize our rule to
Of course, the merging of fire and liquids also raises the possibility of gasoline and explosives, of heating and boiling liquids, etc.: as always, it's wise to incorporate a simulation that is only as detailed as the game's interactions really justify.
276. ★★★ Noisy CricketOur previous experiments into liquid have not dealt with the possibility of mixing components, but that is because for most games, tracking the details of mixture is overkill.
But let's suppose that this time we do want to have mixed liquids; moreover, we want a way to describe the mixtures to the player inventively, so that if he hits specific combinations those combinations are recognized: calling the result a martini, say, rather than just "a mixture of vodka and vermouth".
The implementation that follows relies on a fairly simple idea from linear algebra. Any given liquid can be expressed as a vector in N-space, where N is the number of available ingredients and the length of the vector depends on how much of each ingredient is used; then we find the recipe that best describes the liquid by taking the dot product of our liquid vector with a bunch of sample vectors and selecting the one with the largest result.
If this does not make sense, don't worry: it's not necessary to understand the idea to use the code.
Any implementation involving a large number of place values is always a bit challenging in integer arithmetic. This examples assumes that no bodies of liquid will ever be very large, and that the proportions of ingredients in a mixture will not be vastly askew. (No 20-parts-to-1 proportions, for instance.) This probably works reasonably well for the cocktails that we make the basis of the example.
Our table of mixtures is expressed in parts: so if a recipe contains one part X and two parts Y, we would put "1" in the first column and "2" in the second column.
| rating | creme de menthe comp | vodka comp | cacao comp | adjectival descriptor | nominal descriptor |
| 0.0 fl oz | 1 | 0 | 0 | minty | creme de menthe |
| 0.0 fl oz | 0 | 1 | 0 | chocolatey | vodka |
| 0.0 fl oz | 0 | 0 | 1 | chocolatey | creme de cacao |
| 0.0 fl oz | 1 | 2 | 0 | chocolatey | mintini |
| 0.0 fl oz | 1 | 0 | 1 | chocolatey | grasshopper |
| 0.0 fl oz | 0 | 2 | 1 | chocolatey | chocolate martini |
| 0.0 fl oz | 0 | 3 | 1 | chocolatey | chocolate vodka |
| 0.0 fl oz | 1 | 3 | 0 | chocolatey | mint vodka |
| 0.0 fl oz | 1 | 2 | 1 | chocolatey | chocolate mint martini |
Here we cheat on our arithmetic. The following chart just provides values corresponding roughly to 1/(sqrt (x)), but since Inform does not deal very gracefully with square roots or fractions, we will calculate this elsewhere and just supply the answers in the code:
| initial | result |
| 1 | 100 |
| 2 | 71 |
| 3 | 57 |
| 4 | 50 |
| 5 | 44 |
| 6 | 41 |
| 7 | 38 |
| 8 | 35 |
| 9 | 33 |
| 10 | 31 |
| 11 | 30 |
| 12 | 29 |
| 13 | 28 |
| 14 | 27 |
| 15 | 26 |
| 16 | 25 |
| 17 | 24 |
| 18 | 24 |
| 19 | 23 |
| 20 | 22 |
Much of what follows is identical to "Lemonade" earlier; the new material begins at Part 2.
Here we want Inform to prefer full liquid sources to other containers when it chooses an end to a player's unfinished or ambiguous command. And so:
Both grammar lines point to the same ultimate outcome; the purpose of specifying both is to tell Inform to check thoroughly for full liquid sources before falling back on other fluid containers when making its decisions.
And now we add our liquid source kind, which will represent lakes, absinthe fountains, and any other infinite supplies of liquid we might need. Note that 3276.7 is the largest possible number of fluid ounces available to us.
We want filling things from liquid sources to work the same way as usual, with the distinction that a) the liquid source never depletes in quantity (hence the carry-out rule resetting its fullness); and b) we should report the results a bit differently as well:
On the other hand, pouring liquids into a liquid source needs to work completely differently from pouring liquids into anything else. Let's say we're going to allow any liquid at all to be dumped into rivers and streams (environmental protections evidently are not very well-enforced in this scenario):
A couple of minor refinements:
A slightly tricky situation arises in IF when we want to offer the player a simulation of a near-infinite supply of something: a napkin dispenser from which he can keep taking more napkins, or an infinite selection of pebbles on a beach, or something of that nature.
One approach is simply to limit the number of items the player is allowed to pick up at a time, while maintaining the fiction that there are more of these items in existence than the player is allowed to interact with. Extra Supplies ★★ demonstrates this.
The task becomes harder if we do want to let the player have as many napkins as he wants. In some languages, it is possible to generate new objects on the fly after the story has begun (called "dynamic object creation"), and something like this is possible if we are compiling for Glulx. (See the Inform extensions site for examples.) Usually, though, it is less complicated and almost as effective simply to have a very large supply of existing objects, which are moved in and out of play as the player needs them. Pizza Prince ★ demonstrates how to do this with slices of pizza.
Ropes for an example involving divisible pieces of string, which relies on similar techniques.
Suppose we want the player to have a pizza buffet from which he can take a number of slices. But we don't want to actually put the slices there in front of him, because "you can see 17 slices of pizza here" is not the descriptive effect we want, and because we want to pretend, at least, that the pizza supply is nearly infinite. In fact, we're going to replenish the supply by allowing eaten slices to return to the buffet table (safer in IF than in real life).
To do this, we create one object to stand in for the pizza supply, but whenever the player tries to take it, we give him a different "pizza slice" object instead. Thus:
Now we introduce our actual pizza slices, which are retained in a container out of play until they're needed:
In this example we've set that supply to be artificially small, to make it easier to test what happens when the player reaches the limit; but we could provide many more slices to start with in Pizza Limbo, and the aim in practice would be to pick a number high enough (such as 50 or 100) that the average player will get bored of TAKE PIZZA long before he reaches the limit.
The main thing to be aware of is that objects consume memory in the game file, so creating a large number of pizza slices might bulk the game out. This is more of a concern if we're compiling for the Z-machine than if we're compiling for Glulx.
Whenever the player tries to take the selection, we want him to wind up holding an individual slice instead; but of course we need to check and make sure that he hasn't exhausted the pizza slice supply.
That's fine for the case where the player is taking a new slice of pizza explicitly, but we need to handle it a little differently if the taking action is generated in response to EAT PIZZA. In that case, we need to take the slice and also change the identity of the noun, because after the implicit take action happens, the game will test whether the player is holding the noun before attempting to eat it. So we need to refocus its attention:
And finally, a bit of touch-up:
For tidiness, we should probably also return the consumed pizza slices to Pizza Limbo so that they can be re-used later:
Suppose we have a supply closet in our game from which the player is allowed to take red pens. To keep modeling simple, we only allow him to have one in play at a time, and we test this by seeing whether the red pen is "off-stage" before moving it to his possession.
This approach might seem no different from having a single red pen sitting in the closet, but it may be preferable, for two reasons. First, it's not very plausible for a supply closet to contain nothing but a single red pen (well, assuming a well-regulated supplier, anyway); and second, it gives the player a way to get a new red pen should the original be destroyed in a tragic handwriting accident.
Just as Inform normally assumes everything is solid, it also assumes that these solid objects will not buckle, crack, break or deform under pressure, and cannot be fragmented. But breakability adds realism, and breakage need not be negative: sometimes we want the player to break her way in to something.
In IF the word DROP is more often used to mean "put down" or "leave behind" than "let go from a height": so it is perhaps unfair that in Ming Vase ★ something fragile, when dropped, shatters (into nothing). In Spring Cleaning ★, fragile objects must be explicitly attacked by the player in order to break, and although they leave no tangible debris behind, their loss is at least remembered. Kyoto ★★ provides a general-purpose model for things being thrown at other things, with consequences including things moving (even between rooms) as well as breaking each other.
Debris from breakages is to be avoided if possible because it means keeping track of increasing numbers of objects. But we can increase realism by allowing something to have a visibly "broken" state, which it changes to when it breaks, rather than simply vanishing. Terracottissima ★★ provides for broken and unbroken flowerpots in this way.
Since "part of" allows us to have two objects joined together into what the player sees as one, it also gives us a natural seam which allows the whole to be broken back down into its component parts, and this is the neatest way of providing a breakage into pieces. Paddington ★★ demonstrates a cutting action which allows component parts to be cut away from their holders but will only make small surface gashes in any individual thing: so the player can cut something up, but only into the pieces we specifically choose to allow. Cutting also forces an opening into containers.
Combat and Death for a robot that breaks into its component limbs when shot with a blaster.
Goal-Seeking Characters for a character who eats donuts, leaving crumbs on the floor.
Volume, Height, Weight for containers breaking under the weight of their contents.
Ropes for cutting up string into up to 35 different pieces of different lengths - a limit the player is unlikely to find out about, but a limit all the same, and an expensive solution since we need 35 different things for the "debris" when string is "broken".
In emulation of a certain annoying aspect of the original Adventure, in which there is a Ming vase that cannot safely be dropped:
We could also implement an additional refinement from Adventure, that a fragile thing is safe if dropped when there is a cushion nearby.
In this rule, the pillow is the second noun; if we had a general rule about setting fragile things on soft things, we could say "You set [the noun] down gently on [the second noun]." for the same effect.
If we wanted to be more refined, we would provide extra code so that breaking a container or a supporter would leave behind their contents. We will see how to do that later.
123. ★ Spring CleaningHere we have a destruction action that allows the player to break any fragile items. Once destroyed, these things are removed from play, but we can still refer to them: they are now off-stage. This makes it easy for our sulking character to list the ones that have been destroyed:
Suppose we intend a game in which the player needs to cut things open on a regular basis. We'll want to check whether he has the proper tools handy, and deal graciously with commands such as CUT [something] when no tool is specified. So:
We'll need a way to account for all these cuts and rips.
Moreover, because open containers normally list their contents when examined but we'd prefer Paddington's to be mentioned in the ripping paragraph:
So far, so good. But suppose that we'd like cutting also to make containers be permanently open and impossible to close again. We could write an "instead" rule, but that would mean that only our instead instructions would take effect, overriding the normal cutting it with rules entirely. Better would be to add a second carry out rule:
Now our rule will occur whenever a container is cut, but play will still go on to the reporting stage. And indeed we can add more of these, of varying degrees of specificity:
For that matter, we might want to add a report rule as well, to occur after the "You slash…" rule, so that every time the player cuts something open which has contents, the contents will be listed.
This time we do not add the condition to the rule (i.e., Report cutting an open noun…) If we did, this report rule would be more specific than the general report rule, and would occur first.
Here is a final nicety to get rid of the "which is closed" statement on our closed unopenable teddy bear, using an "activity" rule:
This easiest way to do this uses the "printing the name of" activity, which will come up in the following chapter:
Suppose we want to expand the function of the existing THROW SOMETHING AT command so that a thrown object actually does make contact most of the time. A glance at the Actions index tells us that the Throwing it at rulebook currently looks like this:
| check | an actor throwing something at | implicitly remove thrown clothing rule |
| check | an actor throwing something at | futile to throw things at inanimate objects rule |
| check | an actor throwing something at | block throwing at rule |
Some of those still look useful. We want to leave the "implicitly remove thrown clothing" rule, for instance -- no fair having the player throw a hat that's on his head. On the other hand, the "futile to throw things at inanimate objects rule" is going to have to go, because that would prevent us from ever being able to complete the throwing command. So let's get rid of that:
That "block throwing at" rule also looks sinister: any "block…" rule in the standard actions library is there to print a message telling the player he can't do what he's asked to do.
But it's not enough to ignore it, the way we did the "futile" rule. Since we are only expanding the command to affect inanimate objects, let's replace the "block throwing at" rule with a different one which will only prevent the player throwing things at people:
Now we've changed the command so that some action can sometimes be carried out here -- but we don't have any rules for what happens. It's time to create some rules for our model world.
If we're actually going to allow throwing, we might want to add a couple of extra checks to the rulebook to make sure that this happens when it ought:
And then the rules for the action itself:
That "rule succeeds" ends the action here, if the noun is flat. If not, Inform goes on to the next rule in the carry out throwing it at rulebook:
These rules are assuming some backup information, so let's provide that as well:
Now suppose we'd like to add some further cases for what happens if the player breaks a fragile door this way:
This works, except that objects will continue to "strike" open, unopenable doors, with the result that the player can smash the same door over and over. What we need is another rule, after the aerodynamics rule and before the contact rule, that tells Inform how to handle throwing things at open doors.
If the original rulebook is one we wrote ourselves, we could just add that rule in the proper spot in order. If we got it from an extension, though, we might need to put it in the right place explicitly:
The magic of rulebooks is that they allow authors to amend each other's work (or the Standard Rules) with a fair amount of freedom. A well-written extension will give individual names to its rules, to allow subsequent authors to modify the function of the extension without too much trouble.
Now for an actual scenario with which to test this:
What should fit into what? Inform has basically three sizes: small, person-sized, and room-sized. The difference between "small" and "person-sized" doesn't appear much, but it's the difference between an ordinary container and an enterable container; the fact that a person cannot get inside an ordinary container is one of the few size-related rules built into Inform. It will not object to, say, a fishing rod being put inside a matchbox.
Inform does have one built-in measure of the size of a container: its "carrying capacity". This is a maximum number of contents:
This of course allows three anvils, while forbidding four postage stamps. To do better, we need units of measurement, and Dimensions ★★ demonstrates setting these up. The Speed of Thought ★★, meanwhile, ventures into the area of unit conversion: having multiple types of unit and being able to express them to the player, or parse these in the player's input.
To be fully realistic in what will fit into what, we need sophisticated three-dimensional models of shapes, both of the items being carried and of the free space remaining inside containers. Depth ★ elegantly simplifies this by approximating items as cuboids, with a given width, length and height: these multiply to give a volume. To fit in a container, a new item's volume must not exceed the volume remaining inside the container, and in addition its three dimensions must also fit in one of the possible arrangements at right angles to the sides. (So this system would indeed prevent a 1x1x100 fishing rod from being put inside a 5x2x1 matchbox, but would also prevent a 12x1x1 pencil from being put into a 10x10x1 box, because it would need to be turned diagonally to fit.)
Lead Cuts Paper ★★★ provides a different constraint: here we do not let light-weight containers hold heavy objects.
Weight comes in a different way into Swerve left? Swerve right? Or think about it and die? ★, which exploits up/down map connections to work out which way gravity would take a rolling marble.
Liquids for containers with liquid capacity.
Suppose we have marbles that roll downhill across our map, in a life-size version of one of those marble-chute toys. We might now want to keep track of both compass relationships and which-room-slopes-into-which, so we make a new relation:
And let's say we want the player to be allowed to slide, too, since that would be much more fun than just watching the marbles go:
Now a rule to control what happens to all our sliding and rolling objects:
Since the Ski-jump overlooks the Landing Bowl, the marble will be able to fly through the air to its destination, even though there is no map connection to allow the player to cross. We might want to let the player make it across this barrier also, so:
Because overlooking is various-to-various, we could include that element popular in marble chute toys, the splitter:
In the following, we pretend that every item has a cuboidal shape. Every thing has a length, width and depth, while a "measured container" also has interior dimensions. (Thus a 10x10x10 container with 1cm-thick sides might have interior dimensions 9x9x9.)
In order to see how these shapes might fit together spatially, we need to work out the three dimensions in order of size. (If we were only dealing with portable objects, we could simply insist that the length always be greater than the width which in turn must be greater than the depth, because we could always turn them over in our hands until this was so: but some of the things we deal with may be fixed in place.) A clever way to do this might be to put them in a table of three rows and sort it, but we will write the calculation out longhand:
When testing this example, the author made use of the following: it's no longer needed, but may be useful to anyone else planning elaborations.
We now introduce a new kind: a measured container, which not only has exterior dimensions – the height, width and depth which every thing now has – but also interior measurements. A convenient way to do calculations with the hollow interior is to regard it as if it were a solid shape in its own right, and we do this with the aid of something out of world, which the player never sees: the "imaginary cuboid", which is made into the shape of whatever measured container's interior is being thought about.
If we assume that we could always pack items into a measured container with perfect ease, never wasting any space, then the only volume constraint will be that the total volume of the contents must not exceed the volume of the inside of the container. So we need to calculate the available volume.
If we only constrained volume, a 140 cm-long fishing rod could fit into a 12 cm by 12 cm compact disc box. So we also insist the basic shape must fit, in some orientation perpendicular to one of the sides (i.e.: we can turn the item over in any of its three sides, but not turn it diagonally or wedge it in at a tilt). This requires the longest side of the item to be less than the longest side of the receptacle, and the middle-length side, and also the shortest side. The number of these conditions to fail gives us a clue as to how we can best describe the reason why the shape won't squeeze in.
And finally a situation to try out these rules.
Several warnings about this. First, the numbers can't go very high (if the Settings for the project set the story file format to the Z-machine): while the volume can in theory go to 32,767, in practice this equates to an object 32 cm on a side, which is not very large. One way to avoid this is to use the Glulx format, allowing for sizes in excess of 10 m on a side: or we could simply scale the dimensions to suit our purposes, using a decimeter (10 cm) as the basic unit of measurement, for instance.
Second, the system will require a height, width, and depth for every portable object in the game, which is a large commitment to data entry; it may become tiresome. So it is probably not worth bothering with this kind of simulation unless it is going to be genuinely significant.
258. ★★ DimensionsThe following is not a very sophisticated approach, because it does not allow for weight to accumulate: if we put a gold ingot into a paper bag, then put the bag on the balance platform, only the bag's weight will register. But it will do for a first try.
Suppose that we have a number of objects in the game that are sized in some conventional unit (such as meters), but which we would like to describe in slightly less formal terms. To do this, we will start with measurements as defined in the built-in extension Metric Units, so we don't have to recreate all these.
We'll add our own set of "conceptual units" -- things we're familiar with in real life. As we'll see below, Inform will automatically choose a unit of the right order to express a given distance if we tell it to print a length "in conceptual units".
Note: the following will compile only if you have settings set for Glulx. (To change this, go to the Settings panel and click on the Glulx option.) The Glulx virtual machine is capable of handling larger numbers than the Z-machine.
The following shows the kind of "realism" rules which could be introduced using weights. Not entirely realistic: we do not bother to rupture containers out of the player's sight.
Ropes, chains and similar long, thin, bendable items present three problems: they are like a liquid in that (unless unbreakable) they can be divided arbitrarily into smaller and smaller portions of themselves, they can be in two or more places at once (even in two or more rooms at once), and they can be tied down at either or both ends, allowing them to occupy an uneasy state in between being "portable" and "fixed in place". Even when all this is simulated, they allow us to pull on one end and so to exert force at the other – allowing action-at-a-distance which Inform's realism rules would ordinarily forbid. Ropes are hard. And it is very difficult to imagine everything a player might try when given a fully practical rope with which to solve puzzles.
Snip ★★★ solves the divisibility question, allowing string to be cut or retied into lengths of any size, with all the consequences for describing and understanding that this entails.
Otranto ★★★ provides a lengthy but straightforward approach to the other rope-related issues, subject to the simplifying assumptions that a rope is indivisible, has about the length of the distance between two adjacent rooms, and cannot be tied to another rope.
The range of things one might want to do with a rope in a work of interactive fiction is fairly overwhelming. One might, in theory, swing from ropes; use them to tie containers shut; cut them up into smaller ropes; tie them together into longer ropes; employ them as fuses; bind other characters with them, or the player character.
Our rope implementation is, by these lights, reasonably simple, but it does account for the possibility of tying and untying both ends; using ropes to descend into lower rooms; pulling objects tied to the far end of the rope; and dragging objects from place to place.
We start by coming up with a rope.
Now, we want a rope to be described in terms of the way it is tied, when it's described in a room description.
We need a way to account for it when it's being carried, as well.
And, indeed, whenever the player examines a rope, we should see what's connected.
Similarly, any time the player looks at something tied to a rope.
We also need to make sure that the rope can be interacted with properly even when it's partly in the next room.
Now tying:
Another part of the fun of a rope is that you can drag things from another room:
A player who is tied to things should also have some restrictions on his ability to move.
Sometimes, if the player is tied to a movable object, the moved object will move with him.
And now the actual game and puzzles.
This fudges slightly, since an odd-length string will be divided into uneven halves. Keeping track of fractional inches would complicate matters, though, so let's assume for now that this doesn't matter.
Since our initial string is 36 inches long and it is impossible for the player to divide it into pieces smaller than an inch each, we need a total of 36 items to represent all the string-bits: one that the player carries at the outset, and 35 others. We should bear in mind that it is usually a good idea to use the smallest number of spare objects we can get away with: writing a game that required 1000 strings in the string repository would place silly demands on the resources of the system, so it's best to avoid that sort of thing if possible.
Now with a bit of fiddling we can also teach Inform to recognize descriptors such as "the shortest string":
This is still a little incomplete because we cannot refer to strings by their lengths, as in "the 2 inch string" and so on. To do this, we borrow a line from the chapter on Understanding:
Electrons are so tiny, and move so fast, that we will never want to simulate them in ordinary IF. So we simply regard electricity and magnetism as behaviours which are either present or not present, and which have instantaneous effects.
In Witnessed ★★★, batteries provide electricity to enable a "device" to work. Even if switched on, a device with no battery will be ineffective.
Larger voltages are exposed in Electrified ★, which makes certain items untouchable, and ensures that an experienced electrician will not even try.
Rules of Attraction ★ provides for a magnet which attracts metallic items just strongly enough to stick together until pulled apart for any reason.
Often we have some salient features of an object that we want to make sure the player notices whenever looking at the item in a room or in inventory. At other times, we may prefer to allow the name of the item to be printed bare. So for instance:
Suppose we want to prevent the player from touching anything electrified -- not just as a response to TOUCH OBJECT, but at any time when the action would require contact with the object in question.
The following example makes fairly ample use of material that we haven't seen yet, but gives some idea of the flexibility of every turn rules. Suppose we want to have a number of electrical devices, all of which may be powered by a set of batteries. The batteries will all need to be discharged as they are used (regardless of what device they happen to be controlling at the moment). So:
And to get rid of annoying messages like "Which would you like to close, the flashlight or the flashlight's battery compartment?" when only the compartment is closable, we might add some understanding instructions:
And this last bit, borrowed from the chapter on Understanding, adds some special instructions to help Inform decide when the player is likely to be referring to a compartment and when he's likely to be referring to the device itself.
We also need to deal with commands like PUT BATTERY IN FLASHLIGHT, where Inform might construe BATTERY as the D battery, the flashlight's battery compartment, or the cassette recorder's battery compartment -- and might also construe FLASHLIGHT as either the flashlight's battery compartment or the flashlight itself.
Fire exhibits some of the properties of a gas: it is only vaguely located and tends to spread out, though it passes by touch rather than on the air. It is hazardous to life, through direct contact, heat, and smoke. Better governed, it provides light and warmth. Worse governed, it consumes almost anything it comes into contact with. Here the problem with "debris" is not so much that we need potentially hundreds of new objects to represent broken items: instead, fire could sweep through a work of IF destroying so much that no play is possible any longer. Setting up a problem in which the player must defeat a fully-capable fire is difficult to balance.
As with liquids, it is best to simulate the least amount of fire that the design will allow. Bruneseau's Journey ★★ provides a single candle which can be lit, or blown out, but where fire can never transfer from the candle's end to anything else – or vice versa: the player's source of fire, with which to light the candle, is discreetly neglected.
In the more realistic Thirst 2 ★, a campfire is lit using a tinderbox, so that fire does transfer from one thing (tinder) to another (the campfire): but it is always confined to just these two items, and can be used only for light and warmth.
The Cow Exonerated ★★ provides a class of matches that can light any flammable object, but assumes that burning objects requires only one turn; lighting one thing does not burn another.
In Fire or in Flood ★★★ provides a complete simulation of what we might call "wild-fire": combustion which spreads through arbitrary objects and rooms, destroying all in its path.
Examining for a way to describe objects as charred once they have been partly burnt.
Heat for one consequence of fire having touched something.
Gases for an implementation of smoke without fire, if this can exist.
Liquids for water being used to extinguish a simple fire.
Lighting for other uses of candles and torches as light sources.
Realistically, we ought to attach a randomization to this so that each step of the fire-starting has a good chance of failure. But because our player may not be as patient as someone who actually needs a fire started, we allow him to succeed the first time in every case.
Let's say that our intrepid explorer has a candle that can be lit and blown out again, and should accordingly appear unlit, burning, or partly burnt:
We must be careful: "if the noun was lit" would throw errors because past-tense rules can only be applied to specific items, not to variables that could be anything.
417. ★★ The Cow ExoneratedHere we create a class of matches that can be used to burn other objects. Our objectives are as follow:
Burned objects other than matches should be removed from play instantly (just as edible objects are instantly eaten). We could give everything its own burning duration, but that complicates matters and allows for fire to spread from one object to another; for an example of how to do that, see the example "In Fire or in Flood".
Matches should be described to show whether they are burning or extinguished, and when the parser chooses one of several identical matches, it should make very clear which match it has selected.
The game must sensibly select and, if necessary, automatically light new matches to carry out a >BURN THING command.
The matches must burn for a set number of turns before going out, never to be used again.
And finally, the part for which the text will be useful: when several matches go out in the same turn, we want the game to print
rather than
This last function appears down in Section 3, if we wish to skip ahead and look at it.
The word "matches" is used by Inform to compare snippets of text (see "Reading a command" in the Activities chapter). This can sometimes cause awkwardness if we also have a kind called "match", so for the occasion we will give our matches a more specialized name, never visible to the player:
But that's only a small part of the battle. The thing about fire is that it keeps on doing fiery things even when the player is otherwise occupied: destroying items that are on fire, and spreading to other things nearby. So we need a set of rules for the fire's behavior.
Because we've labelled all the fire rules, we could swap their order, or turn some of them off, while allowing the others run as usual. For instance, if there were a pair of fireproof gloves in the game, we might want to turn off the "can't hold flaming objects rule" whenever the player is wearing them.
This sort of flexibility is especially useful in the context of extensions. Someone writing an extension about burning would have no way of anticipating the need for a Fireproof Gauntlet of Thog, but the author would nonetheless be able to implement one easily.
The contact between things is a critical factor when it comes to fire, so we might add a couple of conditional relations do determine what is touching what.
Having these at our disposal makes it much tidier to write what happens next:
And that completes the rules which cover burning: things can catch fire, fire will spread, and gradually consume the world in flames. All of that was general and could be used in any setting, but we now provide a small game to show it off.
We can then add a special fire rule to handle the trapdoor, which will be called as part of the same sequence. Again, this would be most important if the fire rules were part of a standard extension, and the trapdoor fire rule the author's own addition.
Since we prefer not to simulate burnt skin, and it is unsporting to kill a player outright merely for touching a hot object, heat is mostly used as a reason why something cannot be picked up at a given moment. This very basic puzzle is demonstrated in Grilling ★.
With the naked eye, it is not always easy to detect what is too hot to touch – a point made in both Masochism Deli ★, where the only solution is to keep picking up potatoes until one doesn't burn, and in Hot Glass Looks Like Cold Glass ★★★, where infrared goggles turn the scales.
If a hot object is not to be touched, will it stay hot forever? It might well, if it is a steak on an electric grill, but not if it is a recently-baked apple pie sitting on a window-sill. Entropy ★ simulates the gradual return of temperature to equilibrium.
Electricity and Magnetism for items which shouldn't be touched because they are hot in a different way.
Descriptions of objects can be used in "Instead" rules: we can not only say "Instead of taking the steak", but also "Instead of taking something" or "Instead of taking something which is on the grill".
That last rule is useful if, for example, we want to prevent the player from interacting with anything on a specific supporter:
We could just as easily adapt this rule to affect a container: "Instead of taking something which is in the ice chest," for example.
Note also that in older versions of Inform, the pattern "get all from…" was treated differently from "get steak", and had to be accounted for separately. This is no longer the case; this instead of taking… rule will handle all the phrasings which the player might use to try to acquire this object.
182. ★ EntropyHere the player has several potatoes; we would like to make him more likely to drop the hot one, and more likely to pick up the cold one, all else being equal. At the same time, we want to phrase our rules so that they don't make the player try to take something he's already holding, or drop something he isn't.
So:
Suppose we have a situation where the player is allowed to talk about the heat of an object only if he's properly equipped to detect it.
So far, so good. Now, what if the player tries to GET HOT DISH when the goggles are off? "You can't see any such thing." doesn't seem like quite the right response: he can see such a thing. He just doesn't know which it is.
We could go on to write a mistake rule that would scold the player for trying "get [heat] [text]" when not wearing the goggles. The problem is that this would not cover any other phrasing of the command, nor would it account for all the many other things the player might try to do with an object specified by heat.
What we really want is to catch all instances of the player using the property name when not allowed to do so; and for this purpose we can borrow a trick from the chapter on Activities:
Every previous section of this chapter has been about adding further realism constraints to Inform, to give it a more advanced understanding of physics (and chemistry). But Inform has plenty of physical laws built into it already, even if they are more mundane: inanimate objects do not spontaneously move or change, one solid object cannot pass through another, there are opaque barriers through which light cannot pass, and so on. These rules stop many attempted actions. (GO EAST – "The oak door is closed." GET EMERALD – "You can't, since the glass display case is in the way.")
In the real world, physics is not negotiable. ("Gravity: it's not just a good idea, it's the law.") But in stories, magic can sometimes happen, and in these examples some of the rules built into Inform are waived in special circumstances, which in effect cancel certain physical laws. Very many other magical tricks could be achieved: if you want to make a given command work despite realism constraints, try typing ACTIONS – a testing command which reveals what is happening behind the scenes – and then typing the command you want. This should reveal which named rule is stopping it: you can then try suspending that rule, and seeing if the effect now works.
Magic Words for ways to create new single-word spell commands.
Now the player can get Kitty to take the message without releasing the poisonous gas:
Suppose we want to have a machine in our game that can transmute one item into another, similar object with different properties: a bag of jelly beans into a bag of jewels, for instance. Thus each item will be associated with some number of equivalents -- the other objects it can turn into. This is a handy use for group relations:
In this example we have only defined a single set of transmutable objects, but we could easily expand to include other groups.
(Thanks to Jesse McGrew for proposing this example.)
398. ★ Access All AreasIf somebody tries to walk through a closed door, the "can't go through closed doors rule" usually stops them. This is a rule belonging to the "check going" rulebook. These names are fairly explanatory when written out, but hard to remember: fortunately we don't need to remember them, as the Index panel contains a full inventory of the check, carry out and report rules for every action, showing all of their names and the order in which they are checked. (We can also find out which rules are stopping an action by typing the testing command ACTIONS.)
Here we make the rule do nothing provided a condition holds:
(The Pointy Hat may be useful in debugging a game, even if it never makes it into the final published work.)
It is uncommon, but not absolutely unheard-of, to need to do detailed mathematical calculations in interactive fiction.
The Fibonacci Sequence ★ demonstrates the calculation of a series of numbers; Sieve of Eratosthenes ★ shows off how to calculate the prime numbers within a certain range.
Number Study ★ demonstrates conditional relations between numbers.
This is the same case given above, but expanded just slightly to demonstrate that the names of the relations can also be printed, if we like:
As this shows, we can even form lists of relations. The kind of L is "list of relations of numbers".
433. ★ The Fibonacci SequenceFibonacci (a posthumous nickname) spread Arabic mathematical learning across Europe in the 13th century, and it's curious that his name lives on only for a single sequence.
An array need not be fixed in length, as the following example shows:
The result of "the first 20 terms of the Fibonacci sequence" is "1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584 and 4181". This is a sequence which has a knack of turning up in odd places – it was found in the 1970s to be related to the rings of florets in a sunflower, for instance – and here it is in a book about interactive fiction.
436. ★ Sieve of EratosthenesIn the words of Wikipedia: "Eratosthenes of Cyrene (Greek Eρατοσθένης; 276 BC-194 BC) was a Greek mathematician, poet, athlete, geographer and astronomer." In the words of Tom Lehrer: "It's people like that who make you realise how little you've achieved in life."
A prime number is a number greater than 1 which is not a multiple of anything, so we can find the primes by starting with all the numbers and sieving out all the multiples of 2, then all the multiples of 3, and so on. Here we make our sieve of the unacceptable numbers (the "composite" or non-prime ones) first, then form a list of all the numbers, then sieve out the composites: what are left must be the primes.
While this could all be done more efficiently with an array, that's only because what we are sieving are numbers: sieving is a technique which can be used for non-numerical decisions, too.
When the story file starts up, it often prints a short introductory passage of text (the "overture") and then a heading describing itself, together with some version numbering (the "banner"). It is traditional that the banner must appear eventually (and one of the few requirements of the Inform licence is that the author acknowledge Inform somewhere, for which the banner is sufficient) but some designs call for a multi-turn prologue before the banner finally appears, and marks the start of play in earnest. Bikini Atoll ★ demonstrates this.
If a story file represents the latest in a sequence of story files representing chapters in some larger narrative, it will need some way to pick up where its predecessor left off. This can be done with the aid of external files (in the Glulx format, at least). Alien Invasion Part 23 ★ shows how.
Another task we might want to perform a the beginning of play is to arrange any randomized features that are supposed to change from one playing to the next. We can add such instructions with "When play begins" rule, as in:
Since we may want to do something a bit more complicated than this, Hatless ★★ demonstrates effective and ineffective methods of distributing multiple objects (in this case, one randomly-selected hat per person).
Map for a way to generate a randomized maze at the start of play.
Food for a way to choose a random piece of candy to be poisonous.
Getting Acquainted for a way to choose a murderer from among the characters at the start of each story.
(By tradition, and as a courtesy to all the people who have worked on Inform, authors ensure that the banner is printed some time near the beginning of each game played. So please only defer it, rather than suppress it altogether.)
439. ★ Alien Invasion Part 23Suppose that we have a series of games each of which allows the player to select a puzzle difficulty level. When the player plays a new game in the series, we want him to start out by default with the same difficulty level he faced earlier on, so we store this information in a small preferences file, as follows:
| challenge level |
| easy |
Our preference file is restricted to a single option here for simplicity's sake, but we could keep track of more information -- whether the player preferred verbose or brief room descriptions, screen configurations, and so on.
If we were disposed to be somewhat crueler, we could use a similar method to make the player finish each episode of the series in order to "unlock" the next. All we would need to do is store a numerical password in our preferences file when the player finished a given level; the next level would check, say, the Table of Completed Levels for that password, and refuse to play unless the right number were present.
126. ★★ HatlessSuppose we want a game in which each scenario starts with the characters wearing hats -- randomly passed out. We might be tempted to write our scenario like this:
And we might hope that this would choose a new hatless person for each hat, but we would be wrong. It will instead choose one hatless person and put all the hats on him -- and everyone else has to go bare-headed. That's clearly no good. Let's try again:
But this selects one random hat and assigns it to each hatless person in turn -- so it will only wind up being worn by the last of them (since Inform knows that only one person can wear a hat at a time).
In this case, we do have to expand out our loop so that the game makes an explicit distribution:
Each time Inform considers the instruction "now the item is worn by a random hatless person", there is one fewer such person to choose from -- so we can guarantee that the hats are distributed one per customer and that all hats are distributed.
Hatless 3 is only guaranteed to work because the number of hats is less than or equal to the number of people; otherwise the final use of random will return "nothing" and then a problem message will appear during play.
A very few titles in the IF literature – very few being still too many, some would say – restrict the player's ability to save the story.
Removing the player's ability to UNDO is also a risky choice. Inform does provide the facility with the use option
which makes it impossible to UNDO at any time (unless, that is, the player is playing on an interpreter that itself has a built-in UNDO feature -- these do exist). When it works, undo prevention safeguards a randomized story or combat session against brute-force solutions, but it also means that the player who makes even a minor mistake of typing will be stuck with the undesired results.
In many cases it may be preferable to use some subtler method to enforce random effects in a story. Several extensions exist for Inform that either allow selective manipulation of the UNDO command or rig randomization to prevent UNDO and replay attempts.
The answer is easy, but there is a trap:
The trap is that "Before saving the game…", which might have been our first guess, does not work: because out of world actions are exempt from Before, Instead and After rules.
"Spellbreaker" pulls this unpleasant, but in context witty, stunt as part of a situation which is engineered to force the player to reason through a weighing-objects puzzle using the perfect strategy rather than by guesswork. The illusion that the situation is fair – not rigged against the player, that is – would collapse if the player could save the game and keep retrying possibilities in the light of knowledge gained from earlier attempts. The moral of this story is that any attempt to use in-world situations to influence out-of-world commands should be extremely uncommon.
211. ★★★ A point for never saving the gameHere is one way to score this point with Inform:
That has the right effect, but it just isn't sneaky enough. Instead let us quietly keep track of how many times the player saves:
Sneakier, certainly, but now we could get the bonus even if the game ends earlier on, so finally:
IF is difficult to play: often harder than the writer ever suspects. Players are held up by what is "obvious", and they stumble into unforeseen combinations, or spend inordinate amounts of time working on the "wrong" problems. Too much of this and they give up, or post questions on online forums. Against this, many IF authors like to include in-story hints.
There are many approaches, which differ on two main issues.
First: do we spontaneously offer help to the player? The difficulty here is detecting the player's need: Y ask Y? ★ tries to spot aimlessness, while Solitude ★★ has a novice mode where it is reasonable to assume that help is almost always needed. On the other hand, suppose we require that the initiative come from the player. Will a novice know to type HELP? Query ★ shows how to redirect any attempt to ask a direct question into a HELP request. At the other end of the scale, wearily experienced players may type HELP all the time, out of habit, cheating themselves of the fun of frustration: if so, Real Adventurers Need No Help ★★★ provides the nicotine patch against this addiction.
Second: how do we decide what help is needed? Normally the player only types HELP, which is unspecific. The simplest approach offers a menu, diagnosing the player's problem by obliging him to make choices: see Food Network Interactive ★. Listing all the possible problems in the story may give away too much, though, since players may not have reached the puzzles in question yet; so some authors prefer to create menus that adapt to the current state of the story (commonly called "adaptive hints").
Failing this, we can also try to parse commands like HELP ABOUT MICRODOT, as in Ish. ★ Trieste ★★ takes a similar tack, except that instead of offering hints about puzzles, it offers help on story features (such as how to save), and lists all the available topics if the player types simply HELP.
Finally, and perhaps most stylishly, we can try to deduce what the player is stuck on from his immediate circumstances and from what is not yet solved: this needs a powerful adaptive hints system like the one in The Unexamined Life ★★★.
Getting Started with Conversation for a way to redirect a player using the wrong conversation commands.
Footnotes for another medium by which hints could perhaps be transmitted.
Suppose we'd like to watch for signs that the player is floundering, and if we see them, recommend that he try the hints. There are probably more sophisticated diagnostics, but as a first cut, let's assume that a player who repeatedly reviews descriptions of objects he's already seen, looks around the room, and takes inventory, is at a loss for more productive activities. So then…
And now we write a scenario which will, alas, rather encourage even a deft and clueful player to play as though he were hopelessly confused:
And finally a little dollop of perversity from a later chapter:
"Basic Help Menu" is an extension that uses tables to provide a menu of instructions. Suppose we wanted to include this menu in our own game, but add a few custom menu items of our own:
| title | subtable | description | toggle |
| "Recipes in This Game" | Table of Recipes | -- | -- |
| "Contacting the Author" | -- | "If you have any difficulties with [story title], please contact me at fakeaddress@gmail.com." | -- |
This table is one that is pre-defined by the extension. By continuing it, we add a few additional items to the list.
And since we've promised a sub-menu of recipes:
| title | subtable | description | toggle |
| "Salmon Tartare" | -- | "First, be sure to buy extremely fresh salmon. Raw fish should be served on the day it was caught, if possible. To guarantee this, visit an Asian supermarket or specialty store, and buy salmon marked 'sashimi grade'..." | -- |
| "Pecan Brownies" | -- | "Begin by shelling half a pound of pecans..." | -- |
To test it, type HELP and then experiment.
296. ★ Ish.We can, when necessary, accept any text at all as a token:
After that, we can use "the topic understood" to refer to the text we read:
| topic | title | summary | explanation |
| "sushi" | "sushi" | "Really it's just vinegary rice" | "Popular misconception says that sushi inevitably entails raw fish, but it is in fact just rice with rice vinegar on it. It's just that the really good kinds have raw fish in." |
| "cucumber roll" or "cucumber" | "Cucumber roll" | "Sushi for people who are afraid of sushi" | "It is just rice and slivers of cucumber in the middle, and as long as you don't go too crazy with the wasabi, all should be well." |
| "california roll" or "california" | "California roll" | "Travesty of the sushi concept" | "It's. Fake. Crab." |
| "monkfish liver" | "monkfish liver" | "Expert eaters only" | "The odds of Ichiro's having this unusual delicacy is near zero." |
| "microdot" | "microdot" | "What you came here to deliver" | "There'll be time enough for that later. If Fowler ever turns up. Where is she, anyway?" |
Since the player may not know what all the help options are, we might as well let him get an overview, as well.
First, we create a single "[query]" token so that we can capture all instances of such sentences in a single line:
Now the game will respond to all questions novice players might type with this reminder to look for help information.
285. ★★ TriesteSuppose we are using an extension in which another author has defined some help topics for the player, and we want to amend them for our game.
We'll start with the portion of the text that we have inherited from the extension:
| help-topic | reply |
| commands | "This game recognizes 150 common commands for forms of military attack. These include..." |
| saving | "To save the game, type SAVE. You will be prompted to supply a file-name for your saved game. If you'd like to return to play at that point again later, RESTORE the saved game." |
Now, let's imagine our game is a special one in which only a very limited supply of moves are allowed. In that case, we'll want to replace the information on commands:
| help-topic | reply |
| commands | "The only commands this game recognizes are HOLD, MOVE, CONVOY, SUPPORT MOVE, and SUPPORT HOLD. No others are necessary." |
Observation of novice IF players suggests that they often have a hard time figuring out how to get started, especially if they are encountering the game in a context where they don't have time to settle in and read instructions. Here we provide some training wheels to help them learn to communicate.
This is divided into several parts. The first part is the system of rules for general guidance, which could be excerpted and used anywhere. The second part is a scenario using these rules.
The rationale for asking the question this way, and not another, is that novices asked whether they would like instructions very often say no, even if they need them.
The suggestion about asking for help is no good unless we provide some. This might take any of a number of forms, but for the sake of example we'll use an easy way out:
Suppose we have an action called "asking for help" that gives the player some hints on request. We've also made it possible to turn this feature off, if the player would like to discourage himself from using the hints too much. Now we need a value that varies to keep track of whether hints are currently permitted or currently not permitted. So we might write:
And under the right circumstances, we change hint usage to denied:
Then we can refer back to this value later to decide whether we want to display the hint menu or not:
Note that it would probably be kinder to offer the player some intermediate level of help, in the actual event.
230. ★★★ The Unexamined LifeHint systems in IF come in a variety of flavors: some are a static, prewritten set of guidelines (which might exist in a menu or outside the game entirely); others are built in as part of the program, and attempt to adapt to the situation the player currently faces. Adaptive hints have the advantage that they are less likely to reveal information for which the player is not ready, and the disadvantage that they are more work for the author.
The exercise here is to write an adaptive hint system that will both respond in agile ways to the state of the world model and require a minimum of authorial fussing. We also want the player to be able to ask for a hint about any object he encounters in the game world: this will let him be specific and avoid accidentally receiving hints about the wrong puzzles.
Our baseline assumption is that a player may find a puzzle unsolvable for one of two reasons: he either hasn't seen the relevant clue, or he hasn't got the relevant equipment. If these are true, then he should be given hints about how to find this information, and then once he has it, more specific hints about the puzzle itself -- ending, as a last resort, with the exact command(s) he will need to use in order to bring about the solution.
In practice, there are other possibilities, but this will do for an example.
We begin by defining our relations:
This allows us to create the most absolutely generic sort of hint -- boring, perhaps, but in practice the player often just needs a nudge about what part of the game world he should be examining for a solution:
These things cover hinting about objects that are themselves puzzles. But what if the player asks for hints about a tool or piece of information because he doesn't know how to apply it yet? We might want to give some guidance there, as well.
Now we have these general hints written, but we want to pre-empt them if the player has not yet fulfilled all the prerequisites.
And this business of "seen" things requires, of course, that we keep track:
That "After printing…" rule means that as soon as the game automatically prints the name of an object, it tags that object as having been "seen" by the player. This requires just a little care on our part, that we never mention an object without using the game's printing rules. Still, it is much easier than most other possible forms of bookkeeping.
We also need to deal with the question of whether the player has examined an object, for those objects whose descriptions carry vital information:
In practice, there might be other ways of getting vital facts, and in a more sophisticated puzzle game we might need a more sophisticated model to track this. But examined or unexamined will do for now.
That covers most of the generic hints, but let's also add some slightly more precise hints about a few kinds of objects that are especially important in the model world. These hints will probably not be very interesting to a seasoned IF veteran, but a novice player who does not know the wording or cannot guess what something might be for may still find them useful:
Now to the actual objects in the game:
Notice that we used the bracketed tomb here: the tomb is scenery, and if we do not use the name-printing function, Inform will not register that we have mentioned it to the player.
Now we can add specific hints to replace the generic ones:
The rest of the hint system ensures that the player will not see this final suggestion until he has the pry bar, since the tomb "requires" the pry bar. Having the hint there doesn't excuse us from providing some alternate wording in case the player solves this not-very-difficult conundrum on his own, though:
Note that, if using TEST ME to run through the solution on the Z-machine, we will have to answer a few yes/no questions along the way.
For Glulx, the code should instead read something like
Not every work of IF allots a numerical score to the player: for some authors, this emphasises the idea of a story rather than a narrative. The simple sentence
introduces the concept. Once this is included, Inform will provide built-in support for a single number measuring progress ("score"), and will expect to measure this against a maximum possible ("maximum score", which can either be set by hand or worked out automatically from a table of ranks).
In a story in which scoring exists, the player may choose to turn score notifications (such as "[Your score has just gone up by one point.]") on or off. The commands to do this are NOTIFY ON and NOTIFY OFF; the actions are called switching score notification on and switching score notification off. In the event that we need to amend the behavior of notification, we could do so by adding, removing, or modifying the elements of the check and carry out rulebooks for these commands; as in
If we wish to change the wording of the default message ("[Your score has…"), we may want to use the Responses system.
An especially insidious style of bug allows the player to type the same sequence of commands over and over, earning score endlessly for the same insight, and to avoid this it is usually safest to write source like:
We might also write our condition with "for the first time", like so:
But we should be careful not to use "for the first time" in scoring situations where it's possible for the player to try the action but fail. Inform counts even unsuccessful attempts towards the number of times an action is understood to have occurred, so if the player tries to jump and fails, his "for the first time" will be used up and he will never receive the score points.
If there are many "treasure" items like the Picasso miniature, it is best to be systematic, as in No Place Like Home ★★★. Bosch ★ takes another approach to the same idea, by creating a table of point-earning actions that the player will be rewarded for doing; the FULL SCORE command will then play these back.
Mutt's Adventure ★★ demonstrates how we might add a scored room feature, such that the player earns a point when he first arrives at a special room.
A single number does not really sum up a life, or even an afternoon, and Goat-Cheese and Sage Chicken ★★★ and Panache ★★★ offer more detailed citations. Works that are more story than story may prefer to offer a plot summary of the player's experience to date in lieu of more conventional scoring.
Finally, Rubies ★★★ provides a scoreboard that keeps track of the ten highest-scoring players from one playthrough to the next.
We could, if we wanted, make a table of stored actions all of which represent things that will earn points for the player. For instance:
| relevant action | point value | turn stamp |
| taking the emerald leaf | 15 | -1 |
| eating the gilded lily | 5 | -1 |
(And our list would presumably continue from there, in the full game.)
This system is tidy, but limited: we cannot give actions interesting names in the score list, like "seducing the pirate's daughter" or "collecting a valuable artifact". So it will not be ideal in all situations, but it has the virtue of being easy to extend, and of listing all of the player's successes in the order in which they occurred in his play-through.
136. ★★ Mutt's AdventureSuppose we want to reward the player the first time he reaches a given room. The "unvisited" attribute is useful for this: unlike such constructions as "going to a room for the first time", it doesn't develop false positives when the player has merely tried to go to the room in question. "Every turn when the player is in a room for the first time" is also unhelpful, because it continues to be true as long as the player is in a room on his first visit there.
Suppose we want to assign scores for a whole range of objects the player might pick up. One systematic way to do this would be with a table of point values for things:
| item | score |
| cow | 10 |
| incantations | 4 |
| chessman | 1 |
"Blank out the whole row" removes the line from the table, so that each award will occur only once. The player will not be able to earn more and more points by dropping and taking the same item again.
166. ★★★ PanacheIf we have a plot that branches and has multiple kinds of outcome, we might well want to assemble these into a plot summary in place of the more traditional score. One way to approach this is to build the scene information into a table, adding information when each scene ends.
We begin with a bit of setup:
This next portion borrows from the Advanced Actions chapter to allow us to command Christian to do things:
And now we have enough material to begin writing the scenes:
| event |
| "A Duel of Insults" |
Some games provide a FULL SCORE command that gives more information about the player's achievements than SCORE alone. Supposing we wanted to include a FULL SCORE in our game that gave the kind of score reading described in this chapter:
| Points | Citation | Time |
| 3 | "sauteeing onions" | a time |
| 3 | "reconstituting apricots" | |
| 1 | "flattening chicken" | |
| 1 | "unwrapping goat cheese" |
| Score | Rank |
| 0 | "Rank Amateur" |
| 2 | "would-be Bobby Flay" |
| 5 | "Alton Brown" |
| 8 | "Julia Child" |
And… at that point you're a lot less close to being done than you think. The filling -- onions, sage, apricot, and cheese -- must be assembled and put in the chicken breasts; these tied up in string; each roll dipped in egg yolk and rolled in panko crumbs; these arranged in the Calphalon pan and baked. Then later, the whole retrieved from the oven, and the breasts transferred to a plate while we deglaze the pan and concoct the sauce with the chicken broth, wine, butter, etc. Then the chicken is sliced and plated, and the sauce poured over top. Usually one also wants a side dish or two. A number of things can go interestingly wrong in this process, of course, and implementing it would require, among other things, an intelligent management of all the possible mixtures that result.
441. ★★★ RubiesThe trick here is that we need a table with text in order to keep track of the players' names.
Part 1 largely replicates the source from "Identity Theft"; new material starts at Part 2.
| scored amount | name |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
| 0 | "Smithee" |
And now we introduce a scenario that allows different players to come up with different scores -- admittedly not a very interesting scenario, but it will do for now:
Several default actions allow the player some control over the presentation of the story, or permit the player to request information about what is going on. In addition to the standard commands described elsewhere in this section (SCORE, SAVE, UNDO, QUIT, RESTART, and RESTORE), Inform has the following actions that control the player's experience:
The first three of these allow the player to change the way rooms are described on first and subsequent versions; the last two, when used in a story that provides a score feature, toggle on and off reports such as "[Your score has just gone up by three points.]" These are discussed elsewhere in the Recipe Book (see cross-references below).
These provide immediate feedback about the status of the story file being played:
VERIFY examines checksums to make sure that the story file being run is intact and correct. This is less often an issue now than it was in the days when story files were distributed by highly corruptible floppy disk, but the command persists and is very occasionally useful. VERSION gives the full banner text associated with the story, including title, author, release number, IFID, and other bibliographical data; it follows this with a list of the included extensions.
PRONOUNS announces to the player what the story is currently understanding as the antecedents of "him", "her", "it", and "them". This is often useful during testing, but sometimes also during play.
The following allow the player (when supported by his interpreter) to create a log of play:
It is rarely a good idea to change the default performance of such commands: they are often finicky and closely tied to the interpreter in which the story runs. Moreover, disabling the "version" command means that the story file is not able to display attribution information for Inform and any included extensions, in violation of their respective licenses.
Looking for a way to set the story's verbosity level for the player.
Scoring for a discussion of score notification.
Testing for some examples of status-check commands created for alpha- or beta-testing of a story.
Play can end in many ways, at the writer's discretion:
The phrase "end the story" by itself will finish play, printing "*** The End ***". Using one of the phrases with "saying…" allows us to specify some other text with which to conclude. Including "finally" means that the player has earned access to AMUSING text and other notes, if any of these are provided.
We can eliminate the asterisked headline entirely by removing the rule that prints it, thus:
The next step is to print the player's score and, if applicable, the rank he achieved. By default a story doesn't feature scoring, but the following use option will incorporate it:
Then, if we want to allow a score but alter the way it is reported, we may remove or modify the print final score rule, as in
or perhaps something like
What happens next is normally that the player is invited to RESTART, RESTORE (from a saved story), QUIT or UNDO the last command. The presence of the question can somewhat undercut a tragedy, and Battle of Ridgefield ★ shows another way to go out.
If we do leave the question in, the text is formed by the Table of Final Question Options, which by default looks like this:
| final question wording | only if victorious | topic | final response rule | final response activity |
| "RESTART" | false | "restart" | immediately restart the VM rule | -- |
| "RESTORE a saved story" | false | "restore" | immediately restore saved story rule | -- |
| "see some suggestions for AMUSING things to do" | true | "amusing" | -- | amusing a victorious player |
| "QUIT" | false | "quit" | immediately quit rule | -- |
| "UNDO the last command" | false | "undo" | immediately undo rule | -- |
Because this is a table, we may alter the behavior by changing entries or continuing the table. Finality ★ shows how we might take out the option to UNDO the last command, for instance.
Using an ending phrase that includes "finally" tells Inform to include the options that are marked "only if victorious". One common use is to let the player read some special bit of additional text, perhaps describing easter eggs he might have missed in the story or presenting some authorial notes. Xerxes ★★ demonstrates a simple AMUSING command to read final information, while Jamaica 1688 ★ shows how to add completely new elements to the list of options.
Old-school adventures expected their adventurers to die early and die often. Labyrinth of Ghosts ★★ shows how the residue of such past attempts can be preserved into subsequent attempts, using an external file. Big Sky Country ★★★ shows how a player can be resurrected by, let us say, some beneficent god, so that a player can even die more than once in the same attempt.
Occasionally, a piece of IF is sufficiently serious that it feels bathetic to offer the player the usual restore-restart-undo-quit options at the end. The following would replace "*** You have died ***" with a centered epitaph, then quit the game when the player hits a key.
This example relies on a standard extension to avoid any fancy programming:
By default, Inform reminds the player that he has the option of typing UNDO after a story-ending action. This is generally good practice, especially for the sake of novice players who might not be aware of this possibility otherwise, and might be frustrated by a loss they could easily step back from.
Just occasionally, though, we may decide that the player does not deserve any such notification:
The Table of Final Question Options determines what options are to be given to the player after the story ends. We can change what is mentioned there by altering the entries. (The example Jamaica 1688 explains this table in more detail, and demonstrates some other things that we might do with it.)
And if we decided that we didn't want the player to be able to undo the command at all, we should add the use option
The options offered to the player at the end of the game are listed in the Table of Final Question Options, which means that we can add to them simply by continuing the table; what's more, the table gives us the opportunity to create a "final response rule", a rule that the game should follow in order to parse the player's input at this point.
So, for instance, if we wanted the player to be allowed to ask for notes about any of the rooms, characters, or objects in a historical game:
| final question wording | only if victorious | topic | final response rule | final response activity |
| "REVEAL the inspiration for something or somewhere" | true | "reveal [any thing]" | investigate something rule | -- |
| -- | true | "reveal [any room]" | investigate something rule | -- |
| topic | revelation |
| "reveal [Lucius]" | "Lucius is based on a historical buccaneer who sailed with William Dampier. The original did carry a Greek New Testament, from which he read aloud when the men were stranded in the jungles near Panama." |
| "reveal [Upper Deck]" | "The Callisto is a simplified and tidied representation of a pirate sloop ca. 1688." |
Building a menu is moderately tedious, so we will rely on the standard menu extensions provided. Thus:
| title | subtable | description | toggle |
| "Cult Revisions" | -- | "Did you try... [paragraph break] banning the worship of Seth? [line break] of Dionysus? [line break] assigning all your priests to Re? [line break] assigning male priests to Cybele? [line break] assigning married priestesses to Hestia? [line break] identifying one god as another (e.g., Isis and Hecate)? [line break] identifying a mortal as a god (e.g., Alexander as Helios-Apollo)?" | -- |
| "Military Revisions" | -- | "Did you try... [paragraph break] allying a Greek city-state with the Persians? (try >MEDIZE) [line break] playing Athens as a land-based power?" | -- |
Omitting about a half million words from this rigorous and educational but nonetheless enthralling simulation of centuries of history, culture, and religion, we will skip directly to:
A tradition among Nethack-like computer games of the old school is that a player's death in a given place leaves a ghost behind to haunt subsequent players. Information about past lives is sometimes stored in a "bones file", and in this example we do exactly that, for a grievously unfair little dungeon.
To begin with, the labyrinth itself. We create a kind of value to remember possible means of death in these tunnels, and we assign a coordinate position in some grid to each location. (We do this because grid positions can safely be stored in tables saved out to external files, whereas room names cannot – they represent data which changes each time we amend the source.)
And as compensation for these hazards:
| item | score | |
| silver bars | 3 | |
| platinum pyramid | 10 | |
| emerald | 4 |
We are now ready for the actual undertaking. The Table of Ghostly Presences holds up to twenty death notices, and is initially blank. Deaths are sequentially numbered, and this number is stored in the sequence column.
| haunted position | score at death | turns at death | manner of death | sequence |
| a grid location | a number | a number | a demise | a number |
As the story file starts up, we look to see if a ghosts file already exists. If one does, we load up the Table of Ghostly Presences with it: and if not, as will be the case the first time the player explores, we leave the table blank. We sort the table so that it has earlier deaths (lower sequence numbers) first.
How will ghosts manifest themselves? Because this is only a small example, we will simply tell the player that he senses something. If several ghosts are present in the same place, the most aggrieved (that is, the most recent) is sensed first…
(For instance, "You sense the ghostly presence of an adventurer, buried by a rockfall with a score of 10 in 5 turns.") That just leaves the rule for bumping off the player. When the Table is full, and there are already 20 ghosts, the one who died longest ago (with the lowest sequence count) is eliminated, and his row blanked out. (This will always be row 1 since we sorted the table in sequence order on reading it in.)
Strictly speaking we ought to worry that after 2,147,483,647 deaths, the sequence numbers would grow too large to store in a single value, and then the sequence of ghosts will be erratic. But it seems unlikely that anyone will play this example 2.1 billion times.
138. ★★★ Big Sky CountrySome older games allowed the player to be resurrected after a death, but punished him by distributing his possessions far and wide. Here we emulate that effect.
In a fuller implementation of this game, we might make it possible to get by the snake, but in this version, it's just going to remain troublesome.
"If the player consents" is just a convenient way to ask a yes/no question that the player must answer before going on with the game.
Story files produced by Inform tend not to contain elaborate typographical effects. They would only distract. Like a novel, a classic work of IF is best presented in an elegant but unobtrusive font. Inform does, however, provide for italic and bold-face, and also for a typewriter-style fixed pitch of lettering:
Authors making very frequent use of these might like to borrow the briefer definitions in Chanel Version ★.
A very wide range of letter-forms is normally available (and even more in quoted text), so that the writer seldom needs to not worry whether, say, a sentence like
will work. The Über-complète clavier ★★★ is an exhaustive test of such exotica.
Coloured type is trickier, and its availability depends on the story file format. For a Z-machine story, Garibaldi 2 ★ demonstrates this.
Finally, Tilt 3 ★★ combines unusual letterforms (suit symbols) with red and black colours to render hands of cards typographically.
The extension "Basic Screen Effects" provides a few more type styles, in the form of coloured lettering. The colours available are red, yellow, green, blue, white, magenta, and cyan, as well as the usual black; and to restore the player's default screen colour, we say "default letters".
Thus if we wanted to highlight locked and unlocked doors in our security readout example:
Note that this extension does not currently produce the desired effects when compiling with the Glulx setting; to see it working, make sure that the settings tab is set to compile to the Z-machine.
452. ★ Chanel Version 1HTML uses angled brackets to achieve effects, and places italicised text between and tags; and similarly boldface between and . We can mimic this very easily by setting each up as a segmented substitution:
We have had to use square instead of angle brackets, but then, "in order to be irreplaceable one must always be different" (Coco Chanel).
(Marking these as substitutions which run on prevents unexpected paragraph breaks if they should appear immediately after the end of a sentence.)
449. ★★ Tilt 3Books and articles about card-playing traditionally abbreviate card names into a simple two-symbol notation: a number or letter representing the card rank, followed by a symbol indicating the card suit. Suppose that we want to emulate this notation when taking inventory in our poker game.
The trick here is that colored output is done in different ways by the Z-Machine and by Glulx, so we'll need two different versions of the same section in order to produce this output. The relevant source is right at the beginning:
For the suit symbols, we'll want the Unicode extension included with Inform:
The Basic Screen Effects extension bundled with Inform includes mechanisms to change the text color, so for the Z-machine, we need only include this:
Under Glulx, we need slightly more set-up: Glulx requires that we define special user font styles when we plan to make display changes. A fuller discussion of this (and of how to define new colors) appears in the documentation of "Glulx Text Effects", but an implementation sufficient to our purposes would be
| style name | glulx color |
| special-style-1 | g-pure-red |
| glulx color value | assigned number |
| g-pure-red | 16711680 |
From here, the rest of the source is mostly as we've seen in previous examples:
| term | value | abbrev | topic |
| "ace" | "1" | "A" | "ace/A" |
| "deuce" | "2" | "2" | "deuce/two" |
| "three" | "3" | "3" | "three" |
| "four" | "4" | "4" | "four" |
| "five" | "5" | "5" | "five" |
| "six" | "6" | "6" | "six" |
| "seven" | "7" | "7" | "seven" |
| "eight" | "8" | "8" | "eight" |
| "nine" | "9" | "9" | "nine" |
| "ten" | "10" | "10" | "ten" |
| "jack" | "11" | "J" | "jack/knave/J" |
| "queen" | "12" | "Q" | "queen/Q" |
| "king" | "13" | "K" | "king/K" |
| set suit | set rank | |
| spades | 1 | [royal flush] |
| spades | 13 | |
| spades | 12 | |
| spades | 11 | |
| spades | 10 | |
| clubs | 12 | [straight flush] |
| clubs | 11 | |
| clubs | 10 | |
| clubs | 9 | |
| clubs | 8 | |
| diamonds | 8 | [four of a kind] |
| hearts | 8 | |
| spades | 8 | |
| clubs | 8 | |
| clubs | 3 | |
| clubs | 1 | [full house] |
| spades | 1 | |
| hearts | 10 | |
| spades | 10 | |
| clubs | 10 | |
| hearts | 2 | [flush] |
| hearts | 5 | |
| hearts | 7 | |
| hearts | 11 | |
| hearts | 12 | |
| hearts | 1 | [straight] |
| spades | 13 | |
| diamonds | 12 | |
| clubs | 11 | |
| hearts | 10 | |
| hearts | 2 | [three of a kind] |
| spades | 2 | |
| clubs | 2 | |
| clubs | 4 | |
| spades | 3 | |
| diamonds | 6 | [two pairs] |
| spades | 6 | |
| clubs | 7 | |
| diamonds | 7 | |
| hearts | 9 | |
| diamonds | 6 | [two pairs, ace high] |
| spades | 6 | |
| clubs | 1 | |
| diamonds | 7 | |
| hearts | 1 | |
| hearts | 12 | [pair] |
| spades | 12 | |
| diamonds | 10 | |
| spades | 7 | |
| clubs | 4 | |
| diamonds | 13 | [high] |
| hearts | 11 | |
| spades | 9 | |
| clubs | 7 | |
| diamonds | 5 | |
| hearts | 1 | [tricky sorting: low straight] |
| diamonds | 2 | |
| spades | 3 | |
| diamonds | 4 | |
| diamonds | 5 |
The following example puts Inform's support for exotic lettering through its paces. It was useful in testing Inform but is not a very instructive read: still, it does provide a test story file for interpreters, so we are including the source here as an example.
This example text was used to produce a story file which has been tried against both Zoom for Mac OS X and Windows Frotz. The Latin, Greek, Cyrillic and Hebrew text all functioned perfectly on both, but a point of difference showed when writing the Hebrew alphabet: Zoom wrote this right-to-left, Windows Frotz left-to-right. The exotic symbols displayed on Zoom (though others not mentioned above, such as "[unicode staff of hermes]", did not): but most appeared only as black squares on Windows Frotz, exceptions being the astrological signs for Venus and Mars and the musical note.
The status line is the reverse-coloured bar along the top of the window during play, which conventionally, but not necessarily, shows the current location, the score (or sometimes the time of day) and the number of turns so far. It has been highly traditional since the early 1980s (Infocom's customer newsletter was for many years called "The Status Line"): it has become the visual identifier of IF. It plays the same role for IF that a header with chapter name and page number plays in a printed book.
The status line is ordinarily printed from two named pieces of text, the "left hand status line" and the "right hand status line". These can be changed during play, so for instance,
The examples below offer miscellaneous alternatives, and are fairly self-descriptive.
Viewpoint for a way to make the status line list the player's current identity.
Suppose a game with a large map entirely subdivided into regions. We could define:
Note that, since regions can be stacked, we technically can be within more than one region at once. In the Port Royal example, for instance, the Tavern region is inside the Inland region. If there is any ambiguity, "the map region of the location" will be construed as "the smallest region that the location belongs to": so we would see "Tavern" rather than "Inland" in the status bar, when the player was in the Feathers or the Feathers Bedroom.
Some extra finesse would be necessary if the names of map regions were very long or if there were some rooms that were not considered to belong to any region at all.
350. ★ Ways OutA not-uncommon device in games with large maps is a list of available exits printed in the status bar. We might do this so:
We may find that printing out full directions makes the status line unpleasantly crowded. Fortunately, it isn't hard to provide a set of abbreviations to use in this context:
| heading | shortcut |
| north | "N" |
| northeast | "NE" |
| northwest | "NW" |
| east | "E" |
| southeast | "SE" |
| south | "S" |
| southwest | "SW" |
| west | "W" |
| up | "U" |
| down | "D" |
| inside | "IN" |
| outside | "OUT" |
Everywhere else, the names of directions will still be printed out in full in the usual way.
387. ★ BlanknessOccasionally we want to print something as our first screen and then pause the game. By default, Inform will print a rather odd status line, with "You" on the left side and "0" on the right. This is because the left hand status line is set to display the location, but (because we're not done with the when-play-begins rules) the player has not yet even been moved to a room.
We can tidy this up in the "starting the virtual machine" activity, by temporarily changing the status line content. We will not provide game-pausing code here, because that is easily done by extension; so:
Quite a modest effect, but occasionally useful.
411. ★ Capital CityNot much is needed for this. The only noteworthy point is that it doesn't work by changing the LHSL to "[the player's surroundings in upper case]": it cannot do this because "the player's surroundings" is not a value. Instead, "[the player's surroundings]" is a text substitution sometimes printing the name of a room, sometimes printing "Darkness", and so on. We must therefore load it into a text first, and then apply "…in upper case".
Making major changes to display features, such as the construction of the status line, sometimes requires that we rely on Inform 6 in bulk; here is how we might produce the Trinity-style status line, with the location centered at the top center of the screen.
In fact, as we've already seen, many extra modifications to the display behavior are possible using Basic Screen Effects.
351. ★★ Guided TourIt may sometimes be helpful to prompt the player with a list of exits printed up in the status line. For instance, here is a status line that will print the names of nearby rooms, as well as all the doors the player can see:
Of course, we may not want to tell the player what glories are to be found in locations he hasn't yet explored.
Even when we have seen a room, we might still want a reminder about how to get there:
We may also find that printing out full directions makes the status line unpleasantly crowded. Fortunately, it isn't hard to provide a set of abbreviations to use in this context:
| heading | shortcut |
| north | "N" |
| northeast | "NE" |
| northwest | "NW" |
| east | "E" |
| southeast | "SE" |
| south | "S" |
| southwest | "SW" |
| west | "W" |
| up | "U" |
| down | "D" |
| inside | "in" |
| outside | "out" |
Everywhere else, the names of directions will still be printed out in full in the usual way. And now we give it a little map to work with:
Note that while this looks fine in some places, other locations exceed the limits of what the status-line can hold: if any given room is going to have a large number of exits, this kind of listing will almost certainly not fit. So apply cautiously.
115. ★★★ CenteredIf we want to lay out the status line in some other way than with left-hand and right-hand entries, it is possible to do this as well. Later we will learn about the "rule for constructing the status line", but here is a basic effect using this rule and an Inform extension included as part of the standard distribution, called Basic Screen Effects.
Basic Screen Effects also provides a mechanism for building complicated status lines of more than one row. To read its documentation, we include the extension, press Go!, and then consult the contents index that results.
Ibid. ★★ provides a version of the traditional Infocom-style approach to footnotes, which number off in the order encountered.
"Hitchhiker's Guide to the Galaxy" introduced the idea of footnoted descriptions, and various IF games since have toyed with the idea. The recommended implementation in Inform 6 involved keeping an assortment of footnote objects around, but in Inform 7 the table is a much tidier way of handling the same problem.
| assignment | note |
| a number | "Francis Drake ate here, if the sign on the door is to be believed" |
| -- | "this is unlikely, considering that owls are protected animals in England these days [3 as a footnote]" |
| -- | "moreover, you can't imagine that owl would be very tasty" |
Whenever we mention a footnote for the first time, we need to assign it a number, which we will use consistently thereafter. And it's probably a good idea to protect ourselves against the author accidentally using a number too large for the footnote table, too. So:
Now, in order to let the player view these footnotes, we'll need to parse numbers.
This method does require us to keep track of where a footnote appears in the table. If we found this inconvenient, we could add a column to the footnote table so that we could invoke it with tags like "[appearance quip as a footnote]".
Inform normally expects a purely turn-based story: the player acts, the story responds and waits for the player to act again.
Occasionally, however, we may want to offer a different mode of interaction, for instance with turns in which the player has limited time to come up with his next act. Likewise, we might want to have text that printed itself to the screen gradually, to represent dialogue with pauses, or the speed of a typewriter placing letters on a page.
It's best to be careful with these effects: overdone, they can be very annoying to players who prefer to read at a faster speed. Nonetheless, they do have their uses.
Inform does not have standard syntax to handle real-time delays and output, but there are several extensions that provide this capacity. Erik Temple's extension Real Time Delays, for instance, allows us to specify a delay in milliseconds before continuing with whatever aspect of the story is currently in progress.
The Passage Of Time for ways to keep track of clock-time within the story.
Glulx is one of the two basic story file formats to which Inform can work. It is the more powerful of the two, and modern-day Inform uses it by default. At one time it was a less universally playable format, but today players rarely have any trouble getting it to work.
Among its powers are the ability to display images, play back sound effects, and read and write external files to the disc. With care and a certain amount of fuss, this can even give a playing story file limited Internet connectivity, although it should be stressed that this can only be done if the player sets up his computer just right and runs an auxiliary program beside the story itself. That will mostly be too much to ask, if the player is playing offline, but when the story file is being run on an interpreter running at a server – so that the player simply sends commands to it and sees responses back on a web page – one could easily imagine setting up the server to provide these auxiliary programs, without any extra difficulty for the player.
Many of the more advanced multimedia abilities of Glulx are best unlocked using extensions available from the Inform website or the Public Library. As of this writing, extensions exist to help authors create complex multi-windowed displays (including per-location pictures, visual status bars, and even limited animations and gradually-revealed maps).
There is also work in progress on sound-management to allow the author to play sounds in multiple channels at once, to change sound volumes, and to create fade-in and fade-out effects.
Without extensions, all these abilities are within reach for an author who is willing to do some fairly advanced programming.
This example can only work if we have a separate program running in the background while the story file is being played, and as such it will only work if we set things up in a special way. Exactly how to do this will vary from platform to platform.
First, the source text for the Inform end of the communication line:
As far as the story file is concerned, then, it sends a request down the communication line by writing the chosen RSS feed to the file named "rssrequest", and expects a reply to come back down the line by being written to the file "rssreply". However, the story file needs to expect that this might take some time. (Maybe forever, if there is no program responding, or if the Internet connection is not working.) The story file marks the "rssreply" file as not ready before it makes a request; if it subsequently finds that the file is now ready, that must mean that the other program has done the honours, and that all is well. In the mean time, "The screen remains blank for now."
Now for the RSS-SCRIPT program. The following provides a crude but workable program suitable for running as a Perl script on a system which provides the standard Internet fetching program "curl": Mac OS X, for instance. (If you have OS X, you can paste the following into a (Unix-format) text file called "rss-script.pl", place it in your home folder, open the Terminal utility, type "perl rss-script.pl", and then hide the Terminal window again.)
There are no recipes for testing, alas, although most experienced IF authors have their preferred ways of going about it. Briefly: the best advice is to build and maintain a Skein which holds complete play-throughs of the piece, so that it is easy to check with a single click that all is still well; to have beta-testers who play through (substantial) drafts and send back their transcripts of play, along with suggestions; and to listen to these suggestions, and treat the beta-testers as editors rather than galley slaves.
Alpha ★ shows a way to gracefully accept beta-testers' annotations without advancing time in the story.
Most large works of IF have historically provided secret commands for testing and debugging – commands removed (or sometimes accidentally not) in the final released product. Inform does this automatically: the commands SHOWME, ACTIONS and SCENES are always present except in a released story file. It also allows us to write passages of source text which apply only for the testing phase, so that we can define new testing commands, or other checks that all is well: Bic ★ demonstrates this, and is also useful in its own right.
It may occasionally be useful to check whether all objects in our game have a given property. Here we have a "not for release" section that will run at the start of the game and alert us to any objects lacking description:
Sometimes we want to let testers of a game insert their own comments during a transcript, without those comments wasting turns of the game or producing lengthy or inappropriate parser errors. Many testers have a habit of prefacing comments with a punctuation mark, so let's say that we'd like to catch any command that starts with any punctuation at all:
These three examples simply show what can be done using Inform's EPS-format map output, if one is willing to tweak the design in some vector-art program. Unfortunately, at present, there are few alternatives to Adobe Illustrator – a superb but very expensive program – in the field of EPS editing, and indeed, of vector art generally: this is especially the case for Windows users. Inkscape is a usable free alternative, but it needs to have EPS files translated to PDFs before they can be used. On Mac OS X, the built-in Preview application can do this; otherwise the open-source Ghostscript might be used, but it can be a pain to install. Still, for the IF author who does have EPS editing facilities available, Inform will play nicely with them.
If our map is largely or entirely set inside a single building, we might want to produce something that resembles a floorplan. It's possible to do this with a little tweaking, like so:
Now we have a map made of white lines and boxes over a white background, which is not very exciting. If, however, we put a layer of black under this and slightly adjust the room shapes (using an image editor such as Adobe Illustrator), we can produce something that plausibly resembles a floorplan or museum map, like so:

This sentence has become a long catalogue of specifications. To break it down: we disambiguate the placement of Thames Street End, which otherwise is hard to locate because the directions to and from the room are not symmetrical. Then we apply some general rules about size, font, and color. Finally, we add instructions about offsetting the room locations of a few specific rooms.
This last part is a bit finicky and will not be necessary in many cases, but our goal this time is to create a map diagram that can be superimposed on the real coastal outline of Port Royal at the time. With a bit of editing, the result looks like this:

The map-maker can be used in quite versatile ways, in short; though the default is a schematic line-and-box affair, that is hardly the only option. While the EPS created is not always the result of our dreams, Inform usually can be made to do most of the hard and boring part, leaving the author to do only a bit of aesthetic touchup.
In many previous examples, we have sent hapless deities wandering around a map of Greece; we might like to chart that for ourselves, in a semi-realistic fashion. So:
This produces a line-and-dot map, where the names of rooms do not appear inside the city-circles, but rather (thanks to "room-name-offset") off to one side. We specify a long room-name-length because we want all the names of the cities spelled out in full; and we make all the elements white because we intend to place them over a black background layer.
We can then superimpose this on a vector map of Greece and tweak the exact positions of cities a little by hand (in Adobe Illustrator, as it happens, but other programs would also allow this level of editing). The result:
